]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 5 Jul 2010 03:20:53 +0000 (20:20 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 5 Jul 2010 03:20:53 +0000 (20:20 -0700)
* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  perf, x86: Fix incorrect branches event on AMD CPUs
  perf tools: Fix find tids routine by excluding "." and ".."
  x86: Send a SIGTRAP for user icebp traps

1341 files changed:
.gitignore
Documentation/.gitignore [new file with mode: 0644]
Documentation/ABI/testing/sysfs-bus-pci
Documentation/DocBook/drm.tmpl
Documentation/DocBook/v4l/v4l2.xml
Documentation/DocBook/v4l/vidioc-query-dv-preset.xml
Documentation/edac.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/xfs-delayed-logging-design.txt
Documentation/i2c/busses/i2c-ali1535
Documentation/i2c/busses/i2c-ali1563
Documentation/i2c/busses/i2c-ali15x3
Documentation/i2c/busses/i2c-pca-isa
Documentation/i2c/busses/i2c-sis5595
Documentation/i2c/busses/i2c-sis630
Documentation/i2c/ten-bit-addresses
Documentation/kbuild/kbuild.txt
Documentation/kernel-parameters.txt
Documentation/mutex-design.txt
Documentation/timers/Makefile
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/gspca.txt
Documentation/watchdog/watchdog-parameters.txt
MAINTAINERS
Makefile
arch/alpha/include/asm/bitops.h
arch/alpha/kernel/Makefile
arch/alpha/kernel/ns87312.c [deleted file]
arch/alpha/kernel/pc873xx.c [new file with mode: 0644]
arch/alpha/kernel/pc873xx.h [new file with mode: 0644]
arch/alpha/kernel/pci-sysfs.c
arch/alpha/kernel/sys_sio.c
arch/arm/common/sa1111.c
arch/arm/mach-msm/dma.c
arch/arm/mach-nomadik/clock.c
arch/arm/mach-nomadik/clock.h
arch/arm/mach-nomadik/cpu-8815.c
arch/arm/mach-omap2/board-omap3stalker.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/usb-ehci.c
arch/arm/mach-pxa/palmtc.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-ux500/Makefile
arch/arm/mach-ux500/clock.c
arch/arm/mach-ux500/clock.h
arch/arm/mach-ux500/cpu.c
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mm/copypage-feroceon.c
arch/arm/mm/copypage-v4wb.c
arch/arm/mm/copypage-v4wt.c
arch/arm/mm/copypage-xsc3.c
arch/arm/mm/fault.c
arch/arm/mm/highmem.c
arch/arm/mm/init.c
arch/arm/plat-nomadik/timer.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/iovmm.c
arch/arm/vfp/vfphw.S
arch/cris/arch-v10/drivers/ds1302.c
arch/cris/arch-v10/drivers/pcf8563.c
arch/cris/arch-v10/kernel/irq.c
arch/cris/arch-v10/lib/dmacopy.c
arch/cris/arch-v10/lib/hw_settings.S
arch/cris/arch-v32/drivers/Kconfig
arch/cris/arch-v32/drivers/i2c.c
arch/cris/arch-v32/drivers/pcf8563.c
arch/cris/arch-v32/kernel/crisksyms.c
arch/cris/arch-v32/kernel/irq.c
arch/cris/arch-v32/kernel/smp.c
arch/cris/include/arch-v10/arch/irq.h
arch/cris/include/arch-v32/arch/irq.h
arch/cris/include/asm/param.h
arch/frv/kernel/break.S
arch/frv/kernel/entry.S
arch/frv/kernel/gdb-stub.c
arch/frv/kernel/head.S
arch/frv/kernel/vmlinux.lds.S
arch/frv/mm/fault.c
arch/frv/mm/tlb-miss.S
arch/h8300/boot/compressed/head.S
arch/h8300/boot/compressed/vmlinux.lds
arch/ia64/include/asm/asmmacro.h
arch/ia64/include/asm/cache.h
arch/ia64/include/asm/percpu.h
arch/ia64/kernel/Makefile.gate
arch/ia64/kernel/gate-data.S
arch/ia64/kernel/gate.S
arch/ia64/kernel/gate.lds.S
arch/ia64/kernel/init_task.c
arch/ia64/kernel/ivt.S
arch/ia64/kernel/minstate.h
arch/ia64/kernel/paravirtentry.S
arch/ia64/kernel/vmlinux.lds.S
arch/ia64/kvm/kvm-ia64.c
arch/ia64/kvm/vmm_ivt.S
arch/ia64/mm/tlb.c
arch/ia64/scripts/unwcheck.py
arch/ia64/xen/gate-data.S
arch/ia64/xen/xensetup.S
arch/m32r/mm/fault.c
arch/m68knommu/kernel/vmlinux.lds.S
arch/m68knommu/platform/68360/head-ram.S
arch/m68knommu/platform/68360/head-rom.S
arch/microblaze/include/asm/page.h
arch/microblaze/kernel/dma.c
arch/microblaze/pci/pci-common.c
arch/mips/lasat/image/head.S
arch/mips/lasat/image/romscript.normal
arch/mn10300/mm/fault.c
arch/mn10300/unit-asb2305/pci-asb2305.c
arch/parisc/include/asm/cache.h
arch/parisc/include/asm/system.h
arch/parisc/kernel/head.S
arch/parisc/kernel/init_task.c
arch/parisc/kernel/vmlinux.lds.S
arch/powerpc/Kconfig
arch/powerpc/Kconfig.debug
arch/powerpc/Makefile
arch/powerpc/boot/4xx.c
arch/powerpc/boot/Makefile
arch/powerpc/boot/addRamDisk.c [deleted file]
arch/powerpc/boot/dts/icon.dts [new file with mode: 0644]
arch/powerpc/boot/dts/katmai.dts
arch/powerpc/boot/dts/lite5200.dts
arch/powerpc/boot/dts/lite5200b.dts
arch/powerpc/boot/dts/mpc8548cds.dts
arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
arch/powerpc/boot/dts/p1021mds.dts [new file with mode: 0644]
arch/powerpc/boot/dts/redwood.dts
arch/powerpc/configs/40x/acadia_defconfig
arch/powerpc/configs/40x/ep405_defconfig
arch/powerpc/configs/40x/hcu4_defconfig
arch/powerpc/configs/40x/kilauea_defconfig
arch/powerpc/configs/40x/makalu_defconfig
arch/powerpc/configs/40x/virtex_defconfig
arch/powerpc/configs/40x/walnut_defconfig
arch/powerpc/configs/44x/arches_defconfig
arch/powerpc/configs/44x/bamboo_defconfig
arch/powerpc/configs/44x/canyonlands_defconfig
arch/powerpc/configs/44x/ebony_defconfig
arch/powerpc/configs/44x/eiger_defconfig
arch/powerpc/configs/44x/icon_defconfig [new file with mode: 0644]
arch/powerpc/configs/44x/katmai_defconfig
arch/powerpc/configs/44x/rainier_defconfig
arch/powerpc/configs/44x/redwood_defconfig
arch/powerpc/configs/44x/sam440ep_defconfig
arch/powerpc/configs/44x/sequoia_defconfig
arch/powerpc/configs/44x/taishan_defconfig
arch/powerpc/configs/44x/virtex5_defconfig
arch/powerpc/configs/52xx/cm5200_defconfig
arch/powerpc/configs/52xx/lite5200b_defconfig
arch/powerpc/configs/52xx/motionpro_defconfig
arch/powerpc/configs/52xx/pcm030_defconfig
arch/powerpc/configs/52xx/tqm5200_defconfig
arch/powerpc/configs/86xx/gef_ppc9a_defconfig
arch/powerpc/configs/86xx/gef_sbc310_defconfig
arch/powerpc/configs/86xx/gef_sbc610_defconfig
arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
arch/powerpc/configs/86xx/sbc8641d_defconfig
arch/powerpc/configs/adder875_defconfig
arch/powerpc/configs/amigaone_defconfig
arch/powerpc/configs/c2k_defconfig
arch/powerpc/configs/cell_defconfig
arch/powerpc/configs/celleb_defconfig
arch/powerpc/configs/chrp32_defconfig
arch/powerpc/configs/ep8248e_defconfig
arch/powerpc/configs/ep88xc_defconfig
arch/powerpc/configs/g5_defconfig
arch/powerpc/configs/gamecube_defconfig
arch/powerpc/configs/holly_defconfig
arch/powerpc/configs/iseries_defconfig
arch/powerpc/configs/linkstation_defconfig
arch/powerpc/configs/maple_defconfig
arch/powerpc/configs/mgcoge_defconfig
arch/powerpc/configs/mgsuvd_defconfig
arch/powerpc/configs/mpc512x_defconfig
arch/powerpc/configs/mpc5200_defconfig
arch/powerpc/configs/mpc7448_hpc2_defconfig
arch/powerpc/configs/pasemi_defconfig
arch/powerpc/configs/pmac32_defconfig
arch/powerpc/configs/ppc40x_defconfig
arch/powerpc/configs/ppc44x_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/ppc64e_defconfig
arch/powerpc/configs/pq2fads_defconfig
arch/powerpc/configs/prpmc2800_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/configs/storcenter_defconfig
arch/powerpc/configs/wii_defconfig
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/irq.h
arch/powerpc/include/asm/kdump.h
arch/powerpc/include/asm/kexec.h
arch/powerpc/include/asm/macio.h
arch/powerpc/include/asm/page_64.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/fsl_booke_entry_mapping.S [new file with mode: 0644]
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/machine_kexec_64.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/rtas_flash.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/swsusp_booke.S [new file with mode: 0644]
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/kvm/e500.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/platforms/44x/Kconfig
arch/powerpc/platforms/44x/ppc44x_simple.c
arch/powerpc/platforms/52xx/mpc52xx_pm.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/fsl_msi.h
arch/powerpc/sysdev/fsl_rio.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/ppc4xx_pci.c
arch/powerpc/sysdev/ppc4xx_pci.h
arch/s390/appldata/appldata_os.c
arch/s390/defconfig
arch/s390/include/asm/cache.h
arch/s390/kernel/module.c
arch/s390/kernel/swsusp_asm64.S
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/sigp.c
arch/s390/mm/extmem.c
arch/sh/Kconfig
arch/sh/boards/Kconfig
arch/sh/boards/mach-ap325rxa/setup.c
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-migor/setup.c
arch/sh/boards/mach-se/7724/setup.c
arch/sh/boot/compressed/vmlinux.scr
arch/sh/boot/romimage/Makefile
arch/sh/boot/romimage/head.S
arch/sh/boot/romimage/mmcif-sh7724.c [new file with mode: 0644]
arch/sh/boot/romimage/vmlinux.scr
arch/sh/drivers/pci/pci.c
arch/sh/include/asm/cache.h
arch/sh/include/asm/io.h
arch/sh/include/asm/machvec.h
arch/sh/include/cpu-sh4/cpu/sh7724.h
arch/sh/include/mach-common/mach/romimage.h
arch/sh/include/mach-ecovec24/mach/romimage.h
arch/sh/include/mach-kfr2r09/mach/romimage.h
arch/sh/kernel/Makefile
arch/sh/kernel/dwarf.c
arch/sh/kernel/io.c
arch/sh/kernel/io_generic.c
arch/sh/kernel/io_trapped.c
arch/sh/kernel/machvec.c
arch/sh/kernel/return_address.c
arch/sh/mm/pmb.c
arch/sparc/boot/btfixupprep.c
arch/sparc/include/asm/cache.h
arch/um/include/asm/arch_hweight.h [new file with mode: 0644]
arch/um/kernel/dyn.lds.S
arch/um/kernel/init_task.c
arch/um/kernel/skas/uaccess.c
arch/um/kernel/uml.lds.S
arch/um/os-Linux/mem.c
arch/x86/.gitignore [new file with mode: 0644]
arch/x86/boot/compressed/mkpiggy.c
arch/x86/boot/compressed/vmlinux.lds.S
arch/x86/boot/video-vga.c
arch/x86/include/asm/cache.h
arch/x86/include/asm/io_apic.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/pci_x86.h
arch/x86/include/asm/percpu.h
arch/x86/include/asm/pgtable_32_types.h
arch/x86/include/asm/suspend_32.h
arch/x86/include/asm/suspend_64.h
arch/x86/include/asm/system.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/acpi/wakeup_32.S
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/e820.c
arch/x86/kernel/init_task.c
arch/x86/kernel/mpparse.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup_percpu.c
arch/x86/kernel/sfi.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/mm/numa.c
arch/x86/mm/pat.c
arch/x86/mm/pat_rbtree.c
arch/x86/pci/i386.c
arch/x86/pci/legacy.c
arch/x86/power/cpu.c
arch/x86/xen/suspend.c
arch/xtensa/mm/fault.c
block/blk-core.c
block/cfq-iosched.c
block/cfq.h [new file with mode: 0644]
block/elevator.c
drivers/acpi/acpi_pad.c
drivers/acpi/acpica/acconfig.h
drivers/acpi/acpica/acevents.h
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/achware.h
drivers/acpi/acpica/evgpe.c
drivers/acpi/acpica/evgpeblk.c
drivers/acpi/acpica/evxface.c
drivers/acpi/acpica/evxfevnt.c
drivers/acpi/acpica/exsystem.c
drivers/acpi/acpica/hwgpe.c
drivers/acpi/acpica/hwvalid.c
drivers/acpi/acpica/nsinit.c
drivers/acpi/apei/apei-base.c
drivers/acpi/apei/erst.c
drivers/acpi/atomicio.c
drivers/acpi/blacklist.c
drivers/acpi/button.c
drivers/acpi/ec.c
drivers/acpi/fan.c
drivers/acpi/internal.h
drivers/acpi/processor_driver.c
drivers/acpi/processor_idle.c
drivers/acpi/sleep.c
drivers/acpi/system.c
drivers/acpi/wakeup.c
drivers/ata/Kconfig
drivers/ata/ahci.c
drivers/ata/ata_generic.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/pata_macio.c
drivers/ata/sata_nv.c
drivers/ata/sata_sil24.c
drivers/ata/sata_via.c
drivers/block/brd.c
drivers/block/cciss_scsi.c
drivers/block/cpqarray.c
drivers/block/drbd/drbd_int.h
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_nl.c
drivers/block/drbd/drbd_receiver.c
drivers/block/drbd/drbd_req.c
drivers/block/drbd/drbd_req.h
drivers/block/drbd/drbd_worker.c
drivers/block/swim3.c
drivers/block/virtio_blk.c
drivers/char/Kconfig
drivers/char/agp/generic.c
drivers/char/agp/intel-gtt.c
drivers/char/agp/uninorth-agp.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/n_gsm.c
drivers/char/sysrq.c
drivers/char/tpm/tpm.h
drivers/char/virtio_console.c
drivers/char/vt_ioctl.c
drivers/clocksource/sh_cmt.c
drivers/clocksource/sh_tmu.c
drivers/cpuidle/governors/menu.c
drivers/crypto/amcc/crypto4xx_core.c
drivers/crypto/n2_core.c
drivers/dma/mpc512x_dma.c
drivers/dma/ppc4xx/adma.c
drivers/edac/Kconfig
drivers/edac/Makefile
drivers/edac/amd64_edac.c
drivers/edac/edac_core.h
drivers/edac/edac_mc_sysfs.c
drivers/edac/edac_mce.c [new file with mode: 0644]
drivers/edac/i7core_edac.c [new file with mode: 0644]
drivers/edac/mpc85xx_edac.c
drivers/edac/ppc4xx_edac.c
drivers/firewire/core-card.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/dvo_tfp410.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_trace.h
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_ringbuffer.c [new file with mode: 0644]
drivers/gpu/drm/i915/intel_ringbuffer.h [new file with mode: 0644]
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_crtc.h
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv04_cursor.c
drivers/gpu/drm/nouveau/nv50_cursor.c
drivers/gpu/drm/nouveau/nv50_fb.c
drivers/gpu/drm/nouveau/nv50_gpio.c
drivers/gpu/drm/nouveau/nv50_sor.c
drivers/gpu/drm/radeon/Makefile
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_cs.c [new file with mode: 0644]
drivers/gpu/drm/radeon/evergreen_reg.h
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r200.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_bios.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_cursor.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_fb.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/reg_srcs/evergreen [new file with mode: 0644]
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/ttm/ttm_page_alloc.c
drivers/gpu/drm/vmwgfx/Makefile
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c [new file with mode: 0644]
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/vga/vgaarb.c
drivers/hwmon/adt7411.c
drivers/hwmon/asc7621.c
drivers/hwmon/f75375s.c
drivers/hwmon/g760a.c
drivers/hwmon/i5k_amb.c
drivers/hwmon/k10temp.c
drivers/hwmon/k8temp.c
drivers/hwmon/lm73.c
drivers/hwmon/lm75.c
drivers/hwmon/lm95241.c
drivers/hwmon/tmp102.c
drivers/hwmon/tmp421.c
drivers/hwmon/w83781d.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/i2c-core.c
drivers/i2c/i2c-smbus.c
drivers/ide/pmac.c
drivers/infiniband/hw/qib/qib_fs.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/adp5588-keys.c
drivers/input/keyboard/lm8323.c
drivers/input/keyboard/max7359_keypad.c
drivers/input/keyboard/qt2160.c
drivers/input/keyboard/tca6416-keypad.c
drivers/input/misc/ad714x-i2c.c
drivers/input/misc/hp_sdc_rtc.c
drivers/input/misc/pcf8574_keypad.c
drivers/input/mouse/synaptics_i2c.c
drivers/input/serio/Kconfig
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.h
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/ad7877.c
drivers/input/touchscreen/ad7879.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/eeti_ts.c
drivers/input/touchscreen/mcs5000_ts.c
drivers/input/touchscreen/s3c2410_ts.c
drivers/input/touchscreen/tps6507x-ts.c
drivers/input/touchscreen/tsc2007.c
drivers/isdn/capi/kcapi.c
drivers/isdn/gigaset/asyncdata.c
drivers/isdn/gigaset/capi.c
drivers/isdn/gigaset/common.c
drivers/isdn/gigaset/ev-layer.c
drivers/isdn/gigaset/gigaset.h
drivers/isdn/gigaset/i4l.c
drivers/isdn/gigaset/isocdata.c
drivers/isdn/hardware/mISDN/hfcsusb.c
drivers/isdn/hardware/mISDN/netjet.c
drivers/isdn/hysdn/hysdn_net.c
drivers/leds/leds-bd2802.c
drivers/leds/leds-lp3944.c
drivers/leds/leds-pca9532.c
drivers/leds/leds-pca955x.c
drivers/macintosh/macio_asic.c
drivers/macintosh/mediabay.c
drivers/macintosh/rack-meter.c
drivers/macintosh/therm_adt746x.c
drivers/macintosh/windfarm_lm75_sensor.c
drivers/macintosh/windfarm_max6690_sensor.c
drivers/macintosh/windfarm_smu_sat.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid0.c
drivers/md/raid0.h
drivers/md/raid10.c
drivers/md/raid10.h
drivers/md/raid5.c
drivers/media/IR/Kconfig
drivers/media/IR/imon.c
drivers/media/IR/ir-keytable.c
drivers/media/IR/ir-sysfs.c
drivers/media/IR/keymaps/Makefile
drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c [deleted file]
drivers/media/IR/keymaps/rc-avermedia-m135a.c [new file with mode: 0644]
drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c [new file with mode: 0644]
drivers/media/dvb/dm1105/dm1105.c
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/ttusb2.c
drivers/media/dvb/firewire/firedtv-1394.c
drivers/media/dvb/frontends/au8522_decoder.c
drivers/media/dvb/frontends/ds3000.c
drivers/media/dvb/frontends/stv6110x.c
drivers/media/dvb/ngene/ngene-cards.c
drivers/media/dvb/ngene/ngene-core.c
drivers/media/dvb/ngene/ngene-dvb.c
drivers/media/dvb/ngene/ngene-i2c.c
drivers/media/dvb/ngene/ngene.h
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/radio/si470x/radio-si470x-i2c.c
drivers/media/video/Kconfig
drivers/media/video/ak881x.c
drivers/media/video/bw-qcam.c
drivers/media/video/bw-qcam.h [deleted file]
drivers/media/video/c-qcam.c
drivers/media/video/cx18/cx18-alsa-main.c
drivers/media/video/cx18/cx18-alsa-mixer.c
drivers/media/video/cx18/cx18-alsa-mixer.h
drivers/media/video/cx18/cx18-alsa-pcm.c
drivers/media/video/cx18/cx18-alsa-pcm.h
drivers/media/video/cx18/cx18-alsa.h
drivers/media/video/cx18/cx18-av-audio.c
drivers/media/video/cx18/cx18-av-core.c
drivers/media/video/cx18/cx18-av-core.h
drivers/media/video/cx18/cx18-av-firmware.c
drivers/media/video/cx18/cx18-cards.c
drivers/media/video/cx18/cx18-cards.h
drivers/media/video/cx18/cx18-controls.c
drivers/media/video/cx18/cx18-driver.c
drivers/media/video/cx18/cx18-driver.h
drivers/media/video/cx18/cx18-dvb.c
drivers/media/video/cx18/cx18-fileops.c
drivers/media/video/cx18/cx18-firmware.c
drivers/media/video/cx18/cx18-gpio.c
drivers/media/video/cx18/cx18-gpio.h
drivers/media/video/cx18/cx18-i2c.c
drivers/media/video/cx18/cx18-io.c
drivers/media/video/cx18/cx18-io.h
drivers/media/video/cx18/cx18-ioctl.c
drivers/media/video/cx18/cx18-ioctl.h
drivers/media/video/cx18/cx18-irq.c
drivers/media/video/cx18/cx18-irq.h
drivers/media/video/cx18/cx18-mailbox.c
drivers/media/video/cx18/cx18-mailbox.h
drivers/media/video/cx18/cx18-queue.c
drivers/media/video/cx18/cx18-queue.h
drivers/media/video/cx18/cx18-scb.c
drivers/media/video/cx18/cx18-scb.h
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx18/cx18-streams.h
drivers/media/video/cx231xx/cx231xx-video.c
drivers/media/video/cx2341x.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-i2c.c
drivers/media/video/cx23885/cx23885-input.c
drivers/media/video/cx23885/cx23885-input.h
drivers/media/video/cx23885/cx23885-ioctl.c
drivers/media/video/cx23885/cx23885-ioctl.h
drivers/media/video/cx23885/cx23885-ir.c
drivers/media/video/cx23885/cx23885-ir.h
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx23885/cx23888-ir.c
drivers/media/video/cx23885/cx23888-ir.h
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/gspca/sonixb.c
drivers/media/video/gspca/sonixj.c
drivers/media/video/hdpvr/hdpvr-video.c
drivers/media/video/ivtv/ivtv-controls.c
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-streams.c
drivers/media/video/ivtv/ivtvfb.c
drivers/media/video/mt9m001.c
drivers/media/video/mt9m111.c
drivers/media/video/mt9t031.c
drivers/media/video/mt9t112.c
drivers/media/video/mt9v011.c
drivers/media/video/mt9v022.c
drivers/media/video/mx3_camera.c
drivers/media/video/omap/omap_vout.c
drivers/media/video/ov772x.c
drivers/media/video/ov9640.c
drivers/media/video/pvrusb2/pvrusb2-devattr.c
drivers/media/video/pvrusb2/pvrusb2-devattr.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-main.c
drivers/media/video/pvrusb2/pvrusb2-sysfs.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/pxa_camera.c
drivers/media/video/rj54n1cb0c.c
drivers/media/video/saa7115.c
drivers/media/video/saa7127.c
drivers/media/video/saa7134/saa6752hs.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/saa717x.c
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/sn9c102/sn9c102_devtable.h
drivers/media/video/soc_camera.c
drivers/media/video/soc_camera_platform.c
drivers/media/video/tcm825x.c
drivers/media/video/tvp514x.c
drivers/media/video/tvp5150.c
drivers/media/video/tw9910.c
drivers/media/video/usbvision/usbvision-video.c
drivers/mfd/88pm860x-i2c.c
drivers/mfd/ab3100-core.c
drivers/mfd/ab3550-core.c
drivers/mfd/adp5520.c
drivers/mfd/da903x.c
drivers/mfd/max8925-i2c.c
drivers/mfd/menelaus.c
drivers/mfd/pcf50633-core.c
drivers/mfd/tc35892.c
drivers/mfd/tps65010.c
drivers/mfd/wm8350-i2c.c
drivers/mfd/wm8400-core.c
drivers/misc/eeprom/at24.c
drivers/misc/vmware_balloon.c
drivers/mmc/host/Kconfig
drivers/mmc/host/omap.c
drivers/mmc/host/sh_mmcif.c
drivers/mtd/maps/pismo.c
drivers/mtd/mtdchar.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/fsl_upm.c
drivers/mtd/nand/mpc5121_nfc.c
drivers/mtd/nand/r852.c
drivers/mtd/nand/socrates_nand.c
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/Kconfig
drivers/net/benet/be_cmds.c
drivers/net/bmac.c
drivers/net/bnx2.c
drivers/net/can/mscan/mpc5xxx_can.c
drivers/net/cnic.c
drivers/net/cpmac.c
drivers/net/e1000/e1000_main.c
drivers/net/e1000e/netdev.c
drivers/net/ehea/ehea.h
drivers/net/ehea/ehea_main.c
drivers/net/enic/enic.h
drivers/net/enic/enic_main.c
drivers/net/enic/vnic_dev.c
drivers/net/epic100.c
drivers/net/fec.c
drivers/net/fs_enet/mac-fcc.c
drivers/net/fs_enet/mii-bitbang.c
drivers/net/gianfar.c
drivers/net/greth.c
drivers/net/ixgbe/ixgbe_common.c
drivers/net/ixgbe/ixgbe_ethtool.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ixgbe/ixgbe_phy.c
drivers/net/ixgbe/ixgbe_type.h
drivers/net/korina.c
drivers/net/ksz884x.c
drivers/net/lib82596.c
drivers/net/mace.c
drivers/net/mipsnet.c
drivers/net/netxen/netxen_nic_ctx.c
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_init.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/phy/lxt.c
drivers/net/ppp_generic.c
drivers/net/r8169.c
drivers/net/sfc/net_driver.h
drivers/net/sfc/siena.c
drivers/net/sky2.c
drivers/net/tehuti.c
drivers/net/tulip/de2104x.c
drivers/net/ucc_geth.c
drivers/net/usb/asix.c
drivers/net/usb/hso.c
drivers/net/virtio_net.c
drivers/net/vxge/vxge-main.c
drivers/net/wan/x25_asy.c
drivers/net/wimax/i2400m/fw.c
drivers/net/wireless/ath/ar9170/usb.c
drivers/net/wireless/ath/ath5k/attach.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_hw.c
drivers/net/wireless/hostap/hostap_wlan.h
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl-sta.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/libertas/rx.c
drivers/net/wireless/libertas_tf/main.c
drivers/net/wireless/orinoco/airport.c
drivers/net/wireless/p54/p54pci.c
drivers/net/wireless/p54/p54usb.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/wl12xx/wl1251_sdio.c
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/intel-iommu.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pcie/pme/pcie_pme.c
drivers/pci/quirks.c
drivers/pci/setup-res.c
drivers/pci/slot.c
drivers/pcmcia/ds.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/yenta_socket.c
drivers/platform/x86/intel_scu_ipc.c
drivers/power/max17040_battery.c
drivers/regulator/lp3971.c
drivers/regulator/max1586.c
drivers/regulator/max8649.c
drivers/regulator/max8660.c
drivers/regulator/tps65023-regulator.c
drivers/rtc/rtc-davinci.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1374.c
drivers/rtc/rtc-mpc5121.c
drivers/rtc/rtc-rx8025.c
drivers/rtc/rtc-s35390a.c
drivers/rtc/rtc-s3c.c
drivers/s390/cio/itcw.c
drivers/scsi/mac53c94.c
drivers/scsi/mesh.c
drivers/scsi/sd.c
drivers/serial/8250_pci.c
drivers/serial/altera_uart.c
drivers/serial/bfin_5xx.c
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/serial/msm_serial.c
drivers/serial/msm_serial.h
drivers/serial/pmac_zilog.c
drivers/serial/serial_cs.c
drivers/sfi/sfi_core.c
drivers/sh/intc.c
drivers/spi/mpc512x_psc_spi.c
drivers/spi/spi_ppc4xx.c
drivers/ssb/pci.c
drivers/ssb/sprom.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/adis16255/Kconfig
drivers/staging/adis16255/adis16255.c
drivers/staging/batman-adv/bat_sysfs.c
drivers/staging/batman-adv/device.c
drivers/staging/batman-adv/main.c
drivers/staging/batman-adv/send.c
drivers/staging/comedi/Kconfig
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/drivers/Makefile
drivers/staging/comedi/drivers/addi-data/addi_common.c
drivers/staging/comedi/drivers/addi_apci_035.c
drivers/staging/comedi/drivers/addi_apci_1032.c
drivers/staging/comedi/drivers/addi_apci_1500.c
drivers/staging/comedi/drivers/addi_apci_1516.c
drivers/staging/comedi/drivers/addi_apci_1564.c
drivers/staging/comedi/drivers/addi_apci_16xx.c
drivers/staging/comedi/drivers/addi_apci_1710.c
drivers/staging/comedi/drivers/addi_apci_2016.c
drivers/staging/comedi/drivers/addi_apci_2032.c
drivers/staging/comedi/drivers/addi_apci_2200.c
drivers/staging/comedi/drivers/addi_apci_3001.c
drivers/staging/comedi/drivers/addi_apci_3120.c
drivers/staging/comedi/drivers/addi_apci_3200.c
drivers/staging/comedi/drivers/addi_apci_3300.c
drivers/staging/comedi/drivers/addi_apci_3501.c
drivers/staging/comedi/drivers/addi_apci_3xxx.c
drivers/staging/comedi/drivers/adl_pci9111.c
drivers/staging/comedi/drivers/adv_pci_dio.c
drivers/staging/comedi/drivers/amplc_dio200.c
drivers/staging/comedi/drivers/cb_pcidda.c
drivers/staging/comedi/drivers/ni_mio_cs.c
drivers/staging/comedi/drivers/usbdux.c
drivers/staging/dream/synaptics_i2c_rmi.c
drivers/staging/dt3155/allocator.c
drivers/staging/go7007/wis-saa7113.c
drivers/staging/go7007/wis-saa7115.c
drivers/staging/go7007/wis-sony-tuner.c
drivers/staging/go7007/wis-tw2804.c
drivers/staging/go7007/wis-tw9903.c
drivers/staging/hv/channel_mgmt.c
drivers/staging/hv/hv_utils.c
drivers/staging/hv/vmbus.h
drivers/staging/hv/vmbus_drv.c
drivers/staging/iio/Documentation/iio_utils.h
drivers/staging/iio/adc/max1363_core.c
drivers/staging/iio/light/tsl2563.c
drivers/staging/iio/ring_sw.c
drivers/staging/mrst-touchscreen/Kconfig [new file with mode: 0644]
drivers/staging/mrst-touchscreen/Makefile [new file with mode: 0644]
drivers/staging/mrst-touchscreen/TODO [new file with mode: 0644]
drivers/staging/mrst-touchscreen/intel-mid-touch.c [new file with mode: 0644]
drivers/staging/msm/Kconfig [new file with mode: 0644]
drivers/staging/msm/Makefile [new file with mode: 0644]
drivers/staging/msm/TODO [new file with mode: 0644]
drivers/staging/msm/ebi2_l2f.c [new file with mode: 0644]
drivers/staging/msm/ebi2_lcd.c [new file with mode: 0644]
drivers/staging/msm/ebi2_tmd20.c [new file with mode: 0644]
drivers/staging/msm/hdmi_sii9022.c [new file with mode: 0644]
drivers/staging/msm/lcdc.c [new file with mode: 0644]
drivers/staging/msm/lcdc_external.c [new file with mode: 0644]
drivers/staging/msm/lcdc_gordon.c [new file with mode: 0644]
drivers/staging/msm/lcdc_grapefruit.c [new file with mode: 0644]
drivers/staging/msm/lcdc_panel.c [new file with mode: 0644]
drivers/staging/msm/lcdc_prism.c [new file with mode: 0644]
drivers/staging/msm/lcdc_sharp_wvga_pt.c [new file with mode: 0644]
drivers/staging/msm/lcdc_st15.c [new file with mode: 0644]
drivers/staging/msm/lcdc_st1_wxga.c [new file with mode: 0644]
drivers/staging/msm/lcdc_toshiba_wvga_pt.c [new file with mode: 0644]
drivers/staging/msm/lcdc_wxga.c [new file with mode: 0644]
drivers/staging/msm/logo.c [new file with mode: 0644]
drivers/staging/msm/mddi.c [new file with mode: 0644]
drivers/staging/msm/mddi_ext.c [new file with mode: 0644]
drivers/staging/msm/mddi_ext_lcd.c [new file with mode: 0644]
drivers/staging/msm/mddi_prism.c [new file with mode: 0644]
drivers/staging/msm/mddi_sharp.c [new file with mode: 0644]
drivers/staging/msm/mddi_toshiba.c [new file with mode: 0644]
drivers/staging/msm/mddi_toshiba.h [new file with mode: 0644]
drivers/staging/msm/mddi_toshiba_vga.c [new file with mode: 0644]
drivers/staging/msm/mddi_toshiba_wvga.c [new file with mode: 0644]
drivers/staging/msm/mddi_toshiba_wvga_pt.c [new file with mode: 0644]
drivers/staging/msm/mddihost.c [new file with mode: 0644]
drivers/staging/msm/mddihost.h [new file with mode: 0644]
drivers/staging/msm/mddihost_e.c [new file with mode: 0644]
drivers/staging/msm/mddihosti.c [new file with mode: 0644]
drivers/staging/msm/mddihosti.h [new file with mode: 0644]
drivers/staging/msm/mdp.c [new file with mode: 0644]
drivers/staging/msm/mdp.h [new file with mode: 0644]
drivers/staging/msm/mdp4.h [new file with mode: 0644]
drivers/staging/msm/mdp4_debugfs.c [new file with mode: 0644]
drivers/staging/msm/mdp4_overlay.c [new file with mode: 0644]
drivers/staging/msm/mdp4_overlay_lcdc.c [new file with mode: 0644]
drivers/staging/msm/mdp4_overlay_mddi.c [new file with mode: 0644]
drivers/staging/msm/mdp4_util.c [new file with mode: 0644]
drivers/staging/msm/mdp_cursor.c [new file with mode: 0644]
drivers/staging/msm/mdp_dma.c [new file with mode: 0644]
drivers/staging/msm/mdp_dma_lcdc.c [new file with mode: 0644]
drivers/staging/msm/mdp_dma_s.c [new file with mode: 0644]
drivers/staging/msm/mdp_dma_tv.c [new file with mode: 0644]
drivers/staging/msm/mdp_hw_init.c [new file with mode: 0644]
drivers/staging/msm/mdp_ppp.c [new file with mode: 0644]
drivers/staging/msm/mdp_ppp_dq.c [new file with mode: 0644]
drivers/staging/msm/mdp_ppp_dq.h [new file with mode: 0644]
drivers/staging/msm/mdp_ppp_v20.c [new file with mode: 0644]
drivers/staging/msm/mdp_ppp_v31.c [new file with mode: 0644]
drivers/staging/msm/mdp_vsync.c [new file with mode: 0644]
drivers/staging/msm/memory.c [new file with mode: 0644]
drivers/staging/msm/memory_ll.h [new file with mode: 0644]
drivers/staging/msm/msm_fb.c [new file with mode: 0644]
drivers/staging/msm/msm_fb.h [new file with mode: 0644]
drivers/staging/msm/msm_fb_bl.c [new file with mode: 0644]
drivers/staging/msm/msm_fb_def.h [new file with mode: 0644]
drivers/staging/msm/msm_fb_panel.c [new file with mode: 0644]
drivers/staging/msm/msm_fb_panel.h [new file with mode: 0644]
drivers/staging/msm/msm_mdp.h [new file with mode: 0644]
drivers/staging/msm/staging-devices.c [new file with mode: 0644]
drivers/staging/msm/tv_ntsc.c [new file with mode: 0644]
drivers/staging/msm/tv_pal.c [new file with mode: 0644]
drivers/staging/msm/tvenc.c [new file with mode: 0644]
drivers/staging/msm/tvenc.h [new file with mode: 0644]
drivers/staging/phison/Kconfig
drivers/staging/rt2860/sta_ioctl.c
drivers/staging/rt2860/usb_main_dev.c
drivers/staging/rtl8187se/r8180_core.c
drivers/staging/rtl8192su/r8192U_core.c
drivers/staging/rtl8192u/r8192U_core.c
drivers/staging/sep/sep_driver.c
drivers/staging/tm6000/Kconfig
drivers/staging/tm6000/tm6000-alsa.c
drivers/staging/tm6000/tm6000-cards.c
drivers/staging/tm6000/tm6000-core.c
drivers/staging/tm6000/tm6000-dvb.c
drivers/staging/tm6000/tm6000-video.c
drivers/staging/tm6000/tm6000.h
drivers/staging/usbip/usbip_common.c
drivers/staging/vme/bridges/vme_ca91cx42.c
drivers/staging/vme/bridges/vme_tsi148.c
drivers/staging/wlags49_h2/Kconfig
drivers/staging/wlags49_h2/wl_enc.c
drivers/staging/wlags49_h2/wl_sysfs.h
drivers/staging/wlags49_h25/Kconfig
drivers/staging/xgifb/Kconfig [new file with mode: 0644]
drivers/staging/xgifb/Makefile [new file with mode: 0644]
drivers/staging/xgifb/TODO [new file with mode: 0644]
drivers/staging/xgifb/XGI.h [new file with mode: 0644]
drivers/staging/xgifb/XGI_accel.c [new file with mode: 0644]
drivers/staging/xgifb/XGI_accel.h [new file with mode: 0644]
drivers/staging/xgifb/XGI_main.h [new file with mode: 0644]
drivers/staging/xgifb/XGI_main_26.c [new file with mode: 0644]
drivers/staging/xgifb/XGIfb.h [new file with mode: 0644]
drivers/staging/xgifb/osdef.h [new file with mode: 0644]
drivers/staging/xgifb/vb_def.h [new file with mode: 0644]
drivers/staging/xgifb/vb_ext.c [new file with mode: 0644]
drivers/staging/xgifb/vb_ext.h [new file with mode: 0644]
drivers/staging/xgifb/vb_init.c [new file with mode: 0644]
drivers/staging/xgifb/vb_init.h [new file with mode: 0644]
drivers/staging/xgifb/vb_setmode.c [new file with mode: 0644]
drivers/staging/xgifb/vb_setmode.h [new file with mode: 0644]
drivers/staging/xgifb/vb_struct.h [new file with mode: 0644]
drivers/staging/xgifb/vb_table.h [new file with mode: 0644]
drivers/staging/xgifb/vb_util.c [new file with mode: 0644]
drivers/staging/xgifb/vb_util.h [new file with mode: 0644]
drivers/staging/xgifb/vgatypes.h [new file with mode: 0644]
drivers/usb/class/cdc-acm.c
drivers/usb/core/driver.c
drivers/usb/core/message.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/f_audio.c
drivers/usb/gadget/f_eem.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/fsl_qe_udc.c
drivers/usb/gadget/g_ffs.c
drivers/usb/gadget/m66592-udc.h
drivers/usb/gadget/printer.c
drivers/usb/gadget/r8a66597-udc.c
drivers/usb/gadget/r8a66597-udc.h
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/gadget/u_serial.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-mxc.c
drivers/usb/host/ehci-xilinx-of.c
drivers/usb/host/isp1362-hcd.c
drivers/usb/host/isp1362.h
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/r8a66597.h
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musbhsdma.c
drivers/usb/otg/ulpi.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/mos7840.c
drivers/usb/serial/qcserial.c
drivers/vhost/net.c
drivers/video/Kconfig
drivers/video/aty/mach64_accel.c
drivers/video/backlight/adp8860_bl.c
drivers/video/backlight/tosa_bl.c
drivers/video/bw2.c
drivers/video/cg14.c
drivers/video/cg3.c
drivers/video/fb_defio.c
drivers/video/geode/gxfb_core.c
drivers/video/geode/lxfb_core.c
drivers/video/leo.c
drivers/video/mb862xx/mb862xxfb.c
drivers/video/nuc900fb.c
drivers/video/omap/lcdc.c
drivers/video/omap/rfbi.c
drivers/video/p9100.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/tcx.c
drivers/virtio/virtio_pci.c
drivers/virtio/virtio_ring.c
drivers/watchdog/at32ap700x_wdt.c
drivers/watchdog/gef_wdt.c
drivers/watchdog/imx2_wdt.c
drivers/watchdog/mpc8xxx_wdt.c
drivers/watchdog/wm8350_wdt.c
drivers/xen/xenbus/xenbus_xs.c
fs/afs/server.c
fs/binfmt_elf_fdpic.c
fs/binfmt_flat.c
fs/block_dev.c
fs/btrfs/acl.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/relocation.c
fs/btrfs/root-tree.c
fs/btrfs/super.c
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/mon_client.c
fs/ceph/super.c
fs/cifs/cifsfs.c
fs/cifs/cifsproto.h
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/sess.c
fs/compat.c
fs/configfs/inode.c
fs/dcache.c
fs/ext2/acl.c
fs/ext2/inode.c
fs/ext3/acl.c
fs/ext4/inode.c
fs/ext4/move_extent.c
fs/fcntl.c
fs/fs-writeback.c
fs/fscache/page.c
fs/jffs2/acl.c
fs/jffs2/dir.c
fs/jffs2/fs.c
fs/libfs.c
fs/minix/dir.c
fs/nfs/client.c
fs/nfs/getroot.c
fs/nfs/nfs4xdr.c
fs/nfs/super.c
fs/nfsd/nfs4state.c
fs/nfsd/vfs.c
fs/nilfs2/btree.h
fs/nilfs2/segbuf.h
fs/nilfs2/segment.h
fs/nilfs2/super.c
fs/ocfs2/reservations.c
fs/pipe.c
fs/proc/proc_devtree.c
fs/proc/task_nommu.c
fs/splice.c
fs/super.c
fs/sync.c
fs/sysfs/inode.c
fs/sysv/ialloc.c
fs/ubifs/budget.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_export.c
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_ioctl32.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_quotaops.c
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/linux-2.6/xfs_trace.c
fs/xfs/linux-2.6/xfs_trace.h
fs/xfs/quota/xfs_qm.c
fs/xfs/quota/xfs_qm_syscalls.c
fs/xfs/xfs_ag.h
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_itable.c
fs/xfs/xfs_itable.h
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_rtalloc.h
fs/xfs/xfs_trans.c
fs/xfs/xfs_trans.h
fs/xfs/xfs_trans_inode.c
fs/xfs/xfs_vnodeops.c
include/acpi/acexcep.h
include/acpi/acpixf.h
include/acpi/actypes.h
include/asm-generic/percpu.h
include/asm-generic/vmlinux.lds.h
include/drm/drm_crtc_helper.h
include/drm/i915_drm.h
include/drm/nouveau_drm.h
include/drm/radeon_drm.h
include/drm/vmwgfx_drm.h
include/linux/agp_backend.h
include/linux/backing-dev.h
include/linux/blkdev.h
include/linux/cache.h
include/linux/cgroup.h
include/linux/compiler-gcc.h
include/linux/compiler-gcc4.h
include/linux/drbd.h
include/linux/dynamic_debug.h
include/linux/edac_mce.h [new file with mode: 0644]
include/linux/fb.h
include/linux/fs.h
include/linux/init.h
include/linux/init_task.h
include/linux/iocontext.h
include/linux/libata.h
include/linux/linkage.h
include/linux/list.h
include/linux/miscdevice.h
include/linux/mmc/sh_mmcif.h
include/linux/module.h
include/linux/netfilter/x_tables.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/percpu-defs.h
include/linux/personality.h
include/linux/pipe_fs_i.h
include/linux/sched.h
include/linux/serial_sci.h
include/linux/skbuff.h
include/linux/spinlock.h
include/linux/suspend.h
include/linux/syscalls.h
include/linux/usb/audio-v2.h
include/linux/usb/audio.h
include/linux/vgaarb.h
include/linux/writeback.h
include/media/rc-map.h
include/media/soc_camera.h
include/media/v4l2-mediabus.h
include/media/v4l2-subdev.h
include/net/dst.h
include/net/snmp.h
include/net/sock.h
include/scsi/scsi_host.h
include/trace/events/ext4.h
include/trace/events/sched.h
init/Kconfig
init/main.c
ipc/mqueue.c
kernel/cgroup.c
kernel/cpu.c
kernel/debug/kdb/kdb_main.c
kernel/exec_domain.c
kernel/futex.c
kernel/irq/manage.c
kernel/kexec.c
kernel/module.c
kernel/power/Kconfig
kernel/power/Makefile
kernel/power/nvs.c [moved from kernel/power/hibernate_nvs.c with 80% similarity]
kernel/power/suspend.c
kernel/sched.c
kernel/sched_fair.c
kernel/softirq.c
kernel/stop_machine.c
kernel/sysctl.c
kernel/time/tick-sched.c
kernel/timer.c
lib/atomic64_test.c
lib/dynamic_debug.c
lib/genalloc.c
lib/idr.c
lib/kobject_uevent.c
mm/memcontrol.c
mm/mempolicy.c
mm/page-writeback.c
mm/percpu.c
mm/shmem.c
mm/vmscan.c
net/8021q/vlan_core.c
net/8021q/vlan_dev.c
net/bluetooth/bnep/netdev.c
net/bridge/br_fdb.c
net/bridge/br_forward.c
net/caif/cfrfml.c
net/caif/cfserl.c
net/caif/cfveil.c
net/core/dev.c
net/core/gen_estimator.c
net/core/pktgen.c
net/core/skbuff.c
net/ipv4/Kconfig
net/ipv4/ip_output.c
net/ipv4/ipmr.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/syncookies.c
net/ipv4/tcp_hybla.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/icmp.c
net/ipv6/ip6mr.c
net/ipv6/mcast.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/route.c
net/mac80211/agg-tx.c
net/mac80211/chan.c
net/mac80211/driver-ops.h
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/work.c
net/netfilter/ipvs/ip_vs_conn.c
net/netfilter/x_tables.c
net/phonet/pep.c
net/rds/ib_cm.c
net/rds/iw_cm.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/cls_u32.c
net/sched/sch_teql.c
net/sunrpc/xprtsock.c
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c
scripts/Makefile.build
scripts/Makefile.lib
scripts/Makefile.modbuiltin
scripts/checkincludes.pl
scripts/checkstack.pl
scripts/checkversion.pl
scripts/decodecode
scripts/export_report.pl
scripts/gen_initramfs_list.sh
scripts/genksyms/genksyms.c
scripts/headerdep.pl
scripts/headers_check.pl
scripts/headers_install.pl
scripts/kallsyms.c
scripts/kconfig/Makefile
scripts/kconfig/expr.c
scripts/kconfig/expr.h
scripts/kconfig/gconf.c
scripts/kconfig/gconf.glade
scripts/kconfig/lkc.h
scripts/kconfig/lkc_proto.h
scripts/kconfig/lxdialog/inputbox.c
scripts/kconfig/lxdialog/menubox.c
scripts/kconfig/mconf.c
scripts/kconfig/menu.c
scripts/kconfig/nconf.c [new file with mode: 0644]
scripts/kconfig/nconf.gui.c [new file with mode: 0644]
scripts/kconfig/nconf.h [new file with mode: 0644]
scripts/kconfig/symbol.c
scripts/kconfig/util.c
scripts/kconfig/zconf.tab.c_shipped
scripts/kconfig/zconf.y
scripts/markup_oops.pl
scripts/mkcompile_h
scripts/mod/modpost.c
scripts/namespace.pl
scripts/package/Makefile
scripts/package/builddeb
scripts/package/mkspec
scripts/profile2linkerlist.pl
scripts/rt-tester/rt-tester.py
scripts/setlocalversion
scripts/show_delta
scripts/tags.sh
security/keys/keyctl.c
sound/aoa/soundbus/i2sbus/core.c
sound/atmel/ac97c.c
sound/pci/asihpi/asihpi.c
sound/pci/asihpi/hpi6205.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/fsl/mpc5200_dma.h
sound/soc/imx/Kconfig
sound/soc/pxa/spitz.c
sound/spi/at73c213.c
sound/usb/Makefile
sound/usb/card.c
sound/usb/card.h
sound/usb/clock.c [new file with mode: 0644]
sound/usb/clock.h [new file with mode: 0644]
sound/usb/endpoint.c
sound/usb/format.c
sound/usb/helper.h
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/mixer_maps.c
sound/usb/pcm.c
sound/usb/usbaudio.h
virt/kvm/ioapic.c
virt/kvm/iommu.c

index a2939fc10b225d3727d6501831fad647553f11c8..8faa6c02b39ec3896bd4e989c82ce7f6dbdaf04a 100644 (file)
@@ -28,6 +28,7 @@ modules.builtin
 *.gz
 *.bz2
 *.lzma
+*.lzo
 *.patch
 *.gcno
 
diff --git a/Documentation/.gitignore b/Documentation/.gitignore
new file mode 100644 (file)
index 0000000..bcd907b
--- /dev/null
@@ -0,0 +1,7 @@
+filesystems/dnotify_test
+laptops/dslm
+timers/hpet_example
+vm/hugepage-mmap
+vm/hugepage-shm
+vm/map_hugetlb
+
index 428676cfa61e51917d1fabf0b66e442c943c3768..25be3250f7d66f17c0a4d88974441ced8f4ca633 100644 (file)
@@ -133,46 +133,6 @@ Description:
                The symbolic link points to the PCI device sysfs entry of the
                Physical Function this device associates with.
 
-
-What:          /sys/bus/pci/slots/...
-Date:          April 2005 (possibly older)
-KernelVersion: 2.6.12 (possibly older)
-Contact:       linux-pci@vger.kernel.org
-Description:
-               When the appropriate driver is loaded, it will create a
-               directory per claimed physical PCI slot in
-               /sys/bus/pci/slots/.  The names of these directories are
-               specific to the driver, which in turn, are specific to the
-               platform, but in general, should match the label on the
-               machine's physical chassis.
-
-               The drivers that can create slot directories include the
-               PCI hotplug drivers, and as of 2.6.27, the pci_slot driver.
-
-               The slot directories contain, at a minimum, a file named
-               'address' which contains the PCI bus:device:function tuple.
-               Other files may appear as well, but are specific to the
-               driver.
-
-What:          /sys/bus/pci/slots/.../function[0-7]
-Date:          March 2010
-KernelVersion: 2.6.35
-Contact:       linux-pci@vger.kernel.org
-Description:
-               If PCI slot directories (as described above) are created,
-               and the physical slot is actually populated with a device,
-               symbolic links in the slot directory pointing to the
-               device's PCI functions are created as well.
-
-What:          /sys/bus/pci/devices/.../slot
-Date:          March 2010
-KernelVersion: 2.6.35
-Contact:       linux-pci@vger.kernel.org
-Description:
-               If PCI slot directories (as described above) are created,
-               a symbolic link pointing to the slot directory will be
-               created as well.
-
 What:          /sys/bus/pci/slots/.../module
 Date:          June 2009
 Contact:       linux-pci@vger.kernel.org
index 7583dc7cf64d5b321cd9e50aba766087e07a9fc5..910c923a9b86fe5bbd4e38abd6ad2eb593a25e2b 100644 (file)
       </para>
       <para>
        If your driver supports memory management (it should!), you'll
-       need to set that up at load time as well.  How you intialize
+       need to set that up at load time as well.  How you initialize
        it depends on which memory manager you're using, TTM or GEM.
       </para>
       <sect3>
          aperture space for graphics devices. TTM supports both UMA devices
          and devices with dedicated video RAM (VRAM), i.e. most discrete
          graphics devices.  If your device has dedicated RAM, supporting
-         TTM is desireable.  TTM also integrates tightly with your
+         TTM is desirable.  TTM also integrates tightly with your
          driver specific buffer execution function.  See the radeon
          driver for examples.
        </para>
          likely eventually calling ttm_bo_global_init and
          ttm_bo_global_release, respectively.  Also like the previous
          object, ttm_global_item_ref is used to create an initial reference
-         count for the TTM, which will call your initalization function.
+         count for the TTM, which will call your initialization function.
        </para>
       </sect3>
       <sect3>
@@ -557,7 +557,7 @@ void intel_crt_init(struct drm_device *dev)
          CRT connector and encoder combination is created.  A device
          specific i2c bus is also created, for fetching EDID data and
          performing monitor detection.  Once the process is complete,
-         the new connector is regsitered with sysfs, to make its
+         the new connector is registered with sysfs, to make its
          properties available to applications.
        </para>
        <sect4>
@@ -581,12 +581,12 @@ void intel_crt_init(struct drm_device *dev)
        <para>
          For each encoder, CRTC and connector, several functions must
          be provided, depending on the object type.  Encoder objects
-         need should provide a DPMS (basically on/off) function, mode fixup
+         need to provide a DPMS (basically on/off) function, mode fixup
          (for converting requested modes into native hardware timings),
          and prepare, set and commit functions for use by the core DRM
          helper functions.  Connector helpers need to provide mode fetch and
          validity functions as well as an encoder matching function for
-         returing an ideal encoder for a given connector.  The core
+         returning an ideal encoder for a given connector.  The core
          connector functions include a DPMS callback, (deprecated)
          save/restore routines, detection, mode probing, property handling,
          and cleanup functions.
index 9737243377a3b7ae235f9da9cce41094aed70807..7c3c098d5d08fe080241c82392fabe16814b1653 100644 (file)
@@ -58,7 +58,7 @@ MPEG stream embedded, sliced VBI data format in this specification.
 </contrib>
        <affiliation>
          <address>
-           <email>awalls@radix.net</email>
+           <email>awalls@md.metrocast.net</email>
          </address>
        </affiliation>
       </author>
index 87e4f0f6151cea2c6da8b434b2258300c9f8ce69..402229ee06f61d76bbf62238faec72901c18861b 100644 (file)
@@ -53,8 +53,10 @@ input</refpurpose>
 automatically, similar to sensing the video standard. To do so, applications
 call <constant> VIDIOC_QUERY_DV_PRESET</constant> with a pointer to a
 &v4l2-dv-preset; type. Once the hardware detects a preset, that preset is
-returned in the preset field of &v4l2-dv-preset;. When detection is not
-possible or fails, the value V4L2_DV_INVALID is returned.</para>
+returned in the preset field of &v4l2-dv-preset;. If the preset could not be
+detected because there was no signal, or the signal was unreliable, or the
+signal did not map to a supported preset, then the value V4L2_DV_INVALID is
+returned.</para>
   </refsect1>
 
   <refsect1>
index 79c533223762baa0df825995068b3c6475d90b8b..0b875e8da96965316d0bca49185d5a28b6d25649 100644 (file)
@@ -6,6 +6,8 @@ Written by Doug Thompson <dougthompson@xmission.com>
 7 Dec 2005
 17 Jul 2007    Updated
 
+(c) Mauro Carvalho Chehab <mchehab@redhat.com>
+05 Aug 2009    Nehalem interface
 
 EDAC is maintained and written by:
 
@@ -717,3 +719,153 @@ unique drivers for their hardware systems.
 The 'test_device_edac' sample driver is located at the
 bluesmoke.sourceforge.net project site for EDAC.
 
+=======================================================================
+NEHALEM USAGE OF EDAC APIs
+
+This chapter documents some EXPERIMENTAL mappings for EDAC API to handle
+Nehalem EDAC driver. They will likely be changed on future versions
+of the driver.
+
+Due to the way Nehalem exports Memory Controller data, some adjustments
+were done at i7core_edac driver. This chapter will cover those differences
+
+1) On Nehalem, there are one Memory Controller per Quick Patch Interconnect
+   (QPI). At the driver, the term "socket" means one QPI. This is
+   associated with a physical CPU socket.
+
+   Each MC have 3 physical read channels, 3 physical write channels and
+   3 logic channels. The driver currenty sees it as just 3 channels.
+   Each channel can have up to 3 DIMMs.
+
+   The minimum known unity is DIMMs. There are no information about csrows.
+   As EDAC API maps the minimum unity is csrows, the driver sequencially
+   maps channel/dimm into different csrows.
+
+   For example, suposing the following layout:
+       Ch0 phy rd0, wr0 (0x063f4031): 2 ranks, UDIMMs
+         dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
+         dimm 1 1024 Mb offset: 4, bank: 8, rank: 1, row: 0x4000, col: 0x400
+        Ch1 phy rd1, wr1 (0x063f4031): 2 ranks, UDIMMs
+         dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
+       Ch2 phy rd3, wr3 (0x063f4031): 2 ranks, UDIMMs
+         dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
+   The driver will map it as:
+       csrow0: channel 0, dimm0
+       csrow1: channel 0, dimm1
+       csrow2: channel 1, dimm0
+       csrow3: channel 2, dimm0
+
+exports one
+   DIMM per csrow.
+
+   Each QPI is exported as a different memory controller.
+
+2) Nehalem MC has the hability to generate errors. The driver implements this
+   functionality via some error injection nodes:
+
+   For injecting a memory error, there are some sysfs nodes, under
+   /sys/devices/system/edac/mc/mc?/:
+
+   inject_addrmatch/*:
+      Controls the error injection mask register. It is possible to specify
+      several characteristics of the address to match an error code:
+         dimm = the affected dimm. Numbers are relative to a channel;
+         rank = the memory rank;
+         channel = the channel that will generate an error;
+         bank = the affected bank;
+         page = the page address;
+         column (or col) = the address column.
+      each of the above values can be set to "any" to match any valid value.
+
+      At driver init, all values are set to any.
+
+      For example, to generate an error at rank 1 of dimm 2, for any channel,
+      any bank, any page, any column:
+               echo 2 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/dimm
+               echo 1 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/rank
+
+       To return to the default behaviour of matching any, you can do:
+               echo any >/sys/devices/system/edac/mc/mc0/inject_addrmatch/dimm
+               echo any >/sys/devices/system/edac/mc/mc0/inject_addrmatch/rank
+
+   inject_eccmask:
+       specifies what bits will have troubles,
+
+   inject_section:
+       specifies what ECC cache section will get the error:
+               3 for both
+               2 for the highest
+               1 for the lowest
+
+   inject_type:
+       specifies the type of error, being a combination of the following bits:
+               bit 0 - repeat
+               bit 1 - ecc
+               bit 2 - parity
+
+       inject_enable starts the error generation when something different
+       than 0 is written.
+
+   All inject vars can be read. root permission is needed for write.
+
+   Datasheet states that the error will only be generated after a write on an
+   address that matches inject_addrmatch. It seems, however, that reading will
+   also produce an error.
+
+   For example, the following code will generate an error for any write access
+   at socket 0, on any DIMM/address on channel 2:
+
+   echo 2 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/channel
+   echo 2 >/sys/devices/system/edac/mc/mc0/inject_type
+   echo 64 >/sys/devices/system/edac/mc/mc0/inject_eccmask
+   echo 3 >/sys/devices/system/edac/mc/mc0/inject_section
+   echo 1 >/sys/devices/system/edac/mc/mc0/inject_enable
+   dd if=/dev/mem of=/dev/null seek=16k bs=4k count=1 >& /dev/null
+
+   For socket 1, it is needed to replace "mc0" by "mc1" at the above
+   commands.
+
+   The generated error message will look like:
+
+   EDAC MC0: UE row 0, channel-a= 0 channel-b= 0 labels "-": NON_FATAL (addr = 0x0075b980, socket=0, Dimm=0, Channel=2, syndrome=0x00000040, count=1, Err=8c0000400001009f:4000080482 (read error: read ECC error))
+
+3) Nehalem specific Corrected Error memory counters
+
+   Nehalem have some registers to count memory errors. The driver uses those
+   registers to report Corrected Errors on devices with Registered Dimms.
+
+   However, those counters don't work with Unregistered Dimms. As the chipset
+   offers some counters that also work with UDIMMS (but with a worse level of
+   granularity than the default ones), the driver exposes those registers for
+   UDIMM memories.
+
+   They can be read by looking at the contents of all_channel_counts/
+
+   $ for i in /sys/devices/system/edac/mc/mc0/all_channel_counts/*; do echo $i; cat $i; done
+       /sys/devices/system/edac/mc/mc0/all_channel_counts/udimm0
+       0
+       /sys/devices/system/edac/mc/mc0/all_channel_counts/udimm1
+       0
+       /sys/devices/system/edac/mc/mc0/all_channel_counts/udimm2
+       0
+
+   What happens here is that errors on different csrows, but at the same
+   dimm number will increment the same counter.
+   So, in this memory mapping:
+       csrow0: channel 0, dimm0
+       csrow1: channel 0, dimm1
+       csrow2: channel 1, dimm0
+       csrow3: channel 2, dimm0
+   The hardware will increment udimm0 for an error at the first dimm at either
+       csrow0, csrow2  or csrow3;
+   The hardware will increment udimm1 for an error at the second dimm at either
+       csrow0, csrow2  or csrow3;
+   The hardware will increment udimm2 for an error at the third dimm at either
+       csrow0, csrow2  or csrow3;
+
+4) Standard error counters
+
+   The standard error counters are generated when an mcelog error is received
+   by the driver. Since, with udimm, this is counted by software, it is
+   possible that some errors could be lost. With rdimm's, they displays the
+   contents of the registers
index 672be0109d02617dfa03536c9a4fae7ad4ae4831..c268783bc4e7c18c2e4db792c3fba83d6bc44c71 100644 (file)
@@ -578,15 +578,6 @@ Who:       Avi Kivity <avi@redhat.com>
 
 ----------------------------
 
-What:  "acpi=ht" boot option
-When:  2.6.35
-Why:   Useful in 2003, implementation is a hack.
-       Generally invoked by accident today.
-       Seen as doing more harm than good.
-Who:   Len Brown <len.brown@intel.com>
-
-----------------------------
-
 What:  iwlwifi 50XX module parameters
 When:  2.6.40
 Why:   The "..50" modules parameters were used to configure 5000 series and
index d8119e9d2d60c5af349f6cb96d590e39e9dfdda1..96d0df28bed323d5596fc051b0ffb96ed8e3c8df 100644 (file)
@@ -794,11 +794,6 @@ designed.
 
 Roadmap:
 
-2.6.35 Inclusion in mainline as an experimental mount option
-       => approximately 2-3 months to merge window
-       => needs to be in xfs-dev tree in 4-6 weeks
-       => code is nearing readiness for review
-
 2.6.37 Remove experimental tag from mount option
        => should be roughly 6 months after initial merge
        => enough time to:
index 0db3b4c74ad11109ac59e1486388b5675d49bc56..acbc65a08097777c41d5e400602bde9ed04ae160 100644 (file)
@@ -6,12 +6,12 @@ Supported adapters:
        http://www.ali.com.tw/eng/support/datasheet_request.php
 
 Authors:
-       Frodo Looijaard <frodol@dds.nl>, 
+       Frodo Looijaard <frodol@dds.nl>,
        Philip Edelbrock <phil@netroedge.com>,
        Mark D. Studebaker <mdsxyz123@yahoo.com>,
        Dan Eaton <dan.eaton@rocketlogix.com>,
        Stephen Rousset<stephen.rousset@rocketlogix.com>
-                                                                                               
+
 Description
 -----------
 
index 99ad4b9bcc32ec945235298ee1b9ffd8fbaa3e69..54691698d2ddd465f2a5e9ecd7a1e99ae1da57e5 100644 (file)
@@ -18,7 +18,7 @@ For an overview of these chips see http://www.acerlabs.com
 The M1563 southbridge is deceptively similar to the M1533, with a few
 notable exceptions. One of those happens to be the fact they upgraded the
 i2c core to be SMBus 2.0 compliant, and happens to be almost identical to
-the i2c controller found in the Intel 801 south bridges. 
+the i2c controller found in the Intel 801 south bridges.
 
 Features
 --------
index ff28d381bebe8daa880e344c767e4dad7ff4be14..600da90b8f12138fbf0bd5eb78c2bf0922317443 100644 (file)
@@ -6,8 +6,8 @@ Supported adapters:
        http://www.ali.com.tw/eng/support/datasheet_request.php
 
 Authors:
-       Frodo Looijaard <frodol@dds.nl>, 
-       Philip Edelbrock <phil@netroedge.com>, 
+       Frodo Looijaard <frodol@dds.nl>,
+       Philip Edelbrock <phil@netroedge.com>,
        Mark D. Studebaker <mdsxyz123@yahoo.com>
 
 Module Parameters
@@ -40,10 +40,10 @@ M1541 and M1543C South Bridges.
 The M1543C is a South bridge for desktop systems.
 The M1541 is a South bridge for portable systems.
 They are part of the following ALI chipsets:
-   
- * "Aladdin Pro 2" includes the M1621 Slot 1 North bridge with AGP and 
+
+ * "Aladdin Pro 2" includes the M1621 Slot 1 North bridge with AGP and
                100MHz CPU Front Side bus
- * "Aladdin V" includes the M1541 Socket 7 North bridge with AGP and 100MHz 
+ * "Aladdin V" includes the M1541 Socket 7 North bridge with AGP and 100MHz
                CPU Front Side bus
    Some Aladdin V motherboards:
        Asus P5A
@@ -77,7 +77,7 @@ output of lspci will show something similar to the following:
 ** then run lspci.
 ** If you see the 1533 and 5229 devices but NOT the 7101 device,
 ** then you must enable ACPI, the PMU, SMB, or something similar
-** in the BIOS. 
+** in the BIOS.
 ** The driver won't work if it can't find the M7101 device.
 
 The SMB controller is part of the M7101 device, which is an ACPI-compliant
@@ -87,8 +87,8 @@ The whole M7101 device has to be enabled for the SMB to work. You can't
 just enable the SMB alone. The SMB and the ACPI have separate I/O spaces.
 We make sure that the SMB is enabled. We leave the ACPI alone.
 
-Features 
--------- 
+Features
+--------
 
 This driver controls the SMB Host only. The SMB Slave
 controller on the M15X3 is not enabled. This driver does not use
index 6fc8f4c27c3ce58a12470e11efed3435dede8d85..b044e52654886c05dd37d16212a4cd2cf80419a3 100644 (file)
@@ -1,10 +1,10 @@
 Kernel driver i2c-pca-isa
 
 Supported adapters:
-This driver supports ISA boards using the Philips PCA 9564 
-Parallel bus to I2C bus controller 
+This driver supports ISA boards using the Philips PCA 9564
+Parallel bus to I2C bus controller
 
-Author: Ian Campbell <icampbell@arcom.com>, Arcom Control Systems 
+Author: Ian Campbell <icampbell@arcom.com>, Arcom Control Systems
 
 Module Parameters
 -----------------
@@ -12,12 +12,12 @@ Module Parameters
 * base int
  I/O base address
 * irq int
- IRQ interrupt 
-* clock int 
+ IRQ interrupt
+* clock int
  Clock rate as described in table 1 of PCA9564 datasheet
 
 Description
 -----------
 
-This driver supports ISA boards using the Philips PCA 9564 
-Parallel bus to I2C bus controller 
+This driver supports ISA boards using the Philips PCA 9564
+Parallel bus to I2C bus controller
index cc47db7d00a989da91f6cf99b1578a76ff7cc577..ecd21fb49a8f0c7cd780def05f3ca5408983c3c5 100644 (file)
@@ -1,41 +1,41 @@
 Kernel driver i2c-sis5595
 
-Authors: 
+Authors:
        Frodo Looijaard <frodol@dds.nl>,
         Mark D. Studebaker <mdsxyz123@yahoo.com>,
-       Philip Edelbrock <phil@netroedge.com> 
+       Philip Edelbrock <phil@netroedge.com>
 
 Supported adapters:
   * Silicon Integrated Systems Corp. SiS5595 Southbridge
     Datasheet: Publicly available at the Silicon Integrated Systems Corp. site.
 
-Note: all have mfr. ID 0x1039. 
-
-   SUPPORTED            PCI ID           
-        5595            0008 
-   Note: these chips contain a 0008 device which is incompatible with the 
-         5595. We recognize these by the presence of the listed 
-         "blacklist" PCI ID and refuse to load. 
-   NOT SUPPORTED        PCI ID          BLACKLIST PCI ID         
-         540            0008            0540 
-         550            0008            0550 
-        5513            0008            5511 
-        5581            0008            5597 
-        5582            0008            5597 
-        5597            0008            5597 
-        5598            0008            5597/5598 
-         630            0008            0630 
-         645            0008            0645 
-         646            0008            0646 
-         648            0008            0648 
-         650            0008            0650 
-         651            0008            0651 
-         730            0008            0730 
-         735            0008            0735 
-         745            0008            0745 
-         746            0008            0746 
+Note: all have mfr. ID 0x1039.
+
+   SUPPORTED            PCI ID
+        5595            0008
+
+   Note: these chips contain a 0008 device which is incompatible with the
+         5595. We recognize these by the presence of the listed
+         "blacklist" PCI ID and refuse to load.
+
+   NOT SUPPORTED        PCI ID          BLACKLIST PCI ID
+         540            0008            0540
+         550            0008            0550
+        5513            0008            5511
+        5581            0008            5597
+        5582            0008            5597
+        5597            0008            5597
+        5598            0008            5597/5598
+         630            0008            0630
+         645            0008            0645
+         646            0008            0646
+         648            0008            0648
+         650            0008            0650
+         651            0008            0651
+         730            0008            0730
+         735            0008            0735
+         745            0008            0745
+         746            0008            0746
 
 Module Parameters
 -----------------
index 9aca6889f748e2479052c5c42e9144f852ea42b7..629ea2c356fdb1d00594f57865cbe148c283ee82 100644 (file)
@@ -14,9 +14,9 @@ Module Parameters
 * force = [1|0] Forcibly enable the SIS630. DANGEROUS!
                This can be interesting for chipsets not named
                above to check if it works for you chipset, but DANGEROUS!
-               
-* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default, 
-                       what your BIOS use). DANGEROUS! This should be a bit 
+
+* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default,
+                       what your BIOS use). DANGEROUS! This should be a bit
                        faster, but freeze some systems (i.e. my Laptop).
 
 
@@ -44,6 +44,6 @@ Philip Edelbrock <phil@netroedge.com>
 - testing SiS730 support
 Mark M. Hoffman <mhoffman@lightlink.com>
 - bug fixes
+
 To anyone else which I forgot here ;), thanks!
 
index 200074f8136073bf988463272e0ea269020ac980..e9890709c508b25ed9878ab979797d1fc58a7a4b 100644 (file)
@@ -1,17 +1,17 @@
-The I2C protocol knows about two kinds of device addresses: normal 7 bit 
+The I2C protocol knows about two kinds of device addresses: normal 7 bit
 addresses, and an extended set of 10 bit addresses. The sets of addresses
 do not intersect: the 7 bit address 0x10 is not the same as the 10 bit
 address 0x10 (though a single device could respond to both of them). You
 select a 10 bit address by adding an extra byte after the address
 byte:
-  S Addr7 Rd/Wr ....  
+  S Addr7 Rd/Wr ....
 becomes
   S 11110 Addr10 Rd/Wr
 S is the start bit, Rd/Wr the read/write bit, and if you count the number
 of bits, you will see the there are 8 after the S bit for 7 bit addresses,
 and 16 after the S bit for 10 bit addresses.
 
-WARNING! The current 10 bit address support is EXPERIMENTAL. There are 
+WARNING! The current 10 bit address support is EXPERIMENTAL. There are
 several places in the code that will cause SEVERE PROBLEMS with 10 bit
 addresses, even though there is some basic handling and hooks. Also,
 almost no supported adapter handles the 10 bit addresses correctly.
index 6f8c1cabbc5d1fefe2a18d3c77354b54426d3363..634c625da8ce3435e23118e442c47d2d5b903898 100644 (file)
@@ -65,7 +65,7 @@ CROSS_COMPILE
 Specify an optional fixed part of the binutils filename.
 CROSS_COMPILE can be a part of the filename or the full path.
 
-CROSS_COMPILE is also used for ccache is some setups.
+CROSS_COMPILE is also used for ccache in some setups.
 
 CF
 --------------------------------------------------
@@ -162,3 +162,7 @@ For tags/TAGS/cscope targets, you can specify more than one arch
 to be included in the databases, separated by blank space. E.g.:
 
     $ make ALLSOURCE_ARCHS="x86 mips arm" tags
+
+To get all available archs you can also specify all. E.g.:
+
+    $ make ALLSOURCE_ARCHS=all tags
index 1808f1157f30ae5a187f4a8783d973875cd675dd..82d6aeb5228ff62d71a64e04519c24f35a6116e0 100644 (file)
@@ -2048,7 +2048,9 @@ and is between 256 and 4096 characters. It is defined in the file
                        WARNING: Forcing ASPM on may cause system lockups.
 
        pcie_pme=       [PCIE,PM] Native PCIe PME signaling options:
-               off     Do not use native PCIe PME signaling.
+                       Format: {auto|force}[,nomsi]
+               auto    Use native PCIe PME signaling if the BIOS allows the
+                       kernel to control PCIe config registers of root ports.
                force   Use native PCIe PME signaling even if the BIOS refuses
                        to allow the kernel to control the relevant PCIe config
                        registers.
index aa60d1f627e523929dff9e787498e96ef661cfe6..c91ccc0720fa97f42a1a616fd83e23628ae85ab1 100644 (file)
@@ -66,14 +66,14 @@ of advantages of mutexes:
 
     c0377ccb <mutex_lock>:
     c0377ccb:       f0 ff 08                lock decl (%eax)
-    c0377cce:       78 0e                   js     c0377cde <.text.lock.mutex>
+    c0377cce:       78 0e                   js     c0377cde <.text..lock.mutex>
     c0377cd0:       c3                      ret
 
    the unlocking fastpath is equally tight:
 
     c0377cd1 <mutex_unlock>:
     c0377cd1:       f0 ff 00                lock incl (%eax)
-    c0377cd4:       7e 0f                   jle    c0377ce5 <.text.lock.mutex+0x7>
+    c0377cd4:       7e 0f                   jle    c0377ce5 <.text..lock.mutex+0x7>
     c0377cd6:       c3                      ret
 
  - 'struct mutex' semantics are well-defined and are enforced if
index c85625f4ab257c38d8522c7b669a6a9b82306e89..73f75f8a87dc099f0e788aeb353eb9c3eae50f12 100644 (file)
@@ -2,7 +2,7 @@
 obj- := dummy.o
 
 # List of programs to build
-hostprogs-y := hpet_example
+hostprogs-$(CONFIG_X86) := hpet_example
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
index 070f2576707e16da0600c6a50e2d24d48865914f..1387a69ae3aa5f4842ea522bb5ec4b09a568e41a 100644 (file)
 175 -> Leadtek Winfast DTV1000S                 [107d:6655]
 176 -> Beholder BeholdTV 505 RDS                [0000:5051]
 177 -> Hawell HW-404M7
-179 -> Beholder BeholdTV H7                    [5ace:7190]
-180 -> Beholder BeholdTV A7                    [5ace:7090]
+178 -> Beholder BeholdTV H7                     [5ace:7190]
+179 -> Beholder BeholdTV A7                     [5ace:7090]
+180 -> Avermedia M733A                          [1461:4155,1461:4255]
index 8f3f5d33327ce0341b545ba68dd8d8991640f233..f13eb036c439a4af60310fff845a4e3b82552fa5 100644 (file)
@@ -290,6 +290,7 @@ sonixb              0c45:602e       Genius VideoCam Messenger
 sonixj         0c45:6040       Speed NVC 350K
 sonixj         0c45:607c       Sonix sn9c102p Hv7131R
 sonixj         0c45:60c0       Sangha Sn535
+sonixj         0c45:60ce       USB-PC-Camera-168 (TALK-5067)
 sonixj         0c45:60ec       SN9C105+MO4000
 sonixj         0c45:60fb       Surfer NoName
 sonixj         0c45:60fc       LG-LIC300
index 41c95cc1dc1ff990f27d9b83647770d65a171745..17ddd822b4563c2cdf80ba80f422db5b4b35e002 100644 (file)
@@ -125,6 +125,11 @@ ibmasr:
 nowayout: Watchdog cannot be stopped once started
        (default=kernel config parameter)
 -------------------------------------------------
+imx2_wdt:
+timeout: Watchdog timeout in seconds (default 60 s)
+nowayout: Watchdog cannot be stopped once started
+       (default=kernel config parameter)
+-------------------------------------------------
 indydog:
 nowayout: Watchdog cannot be stopped once started
        (default=kernel config parameter)
index 13608bd2e7913941bae445f08c201912f798c2fd..a07a49deb47bb725c701cdf0320377bf9702e153 100644 (file)
@@ -896,11 +896,13 @@ S:        Maintained
 
 ARM/SAMSUNG ARM ARCHITECTURES
 M:     Ben Dooks <ben-linux@fluff.org>
+M:     Kukjin Kim <kgene.kim@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.fluff.org/ben/linux/
 S:     Maintained
-F:     arch/arm/plat-s3c/
+F:     arch/arm/plat-samsung/
 F:     arch/arm/plat-s3c24xx/
+F:     arch/arm/plat-s5p/
 
 ARM/S3C2410 ARM ARCHITECTURE
 M:     Ben Dooks <ben-linux@fluff.org>
@@ -1148,7 +1150,7 @@ F:        drivers/mmc/host/atmel-mci.c
 F:     drivers/mmc/host/atmel-mci-regs.h
 
 ATMEL AT91 / AT32 SERIAL DRIVER
-M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Supported
 F:     drivers/serial/atmel_serial.c
 
@@ -1160,18 +1162,18 @@ F:      drivers/video/atmel_lcdfb.c
 F:     include/video/atmel_lcdc.h
 
 ATMEL MACB ETHERNET DRIVER
-M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Supported
 F:     drivers/net/macb.*
 
 ATMEL SPI DRIVER
-M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Supported
 F:     drivers/spi/atmel_spi.*
 
 ATMEL USBA UDC DRIVER
-M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
-L:     kernel@avr32linux.org
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver
 S:     Supported
 F:     drivers/usb/gadget/atmel_usba_udc.*
@@ -1581,7 +1583,7 @@ F:        include/linux/coda*.h
 
 COMMON INTERNET FILE SYSTEM (CIFS)
 M:     Steve French <sfrench@samba.org>
-L:     linux-cifs-client@lists.samba.org (moderated for non-subscribers)
+L:     linux-cifs@vger.kernel.org
 L:     samba-technical@lists.samba.org (moderated for non-subscribers)
 W:     http://linux-cifs.samba.org/
 Q:     http://patchwork.ozlabs.org/project/linux-cifs-client/list/
@@ -1731,7 +1733,7 @@ S:        Maintained
 F:     sound/pci/cs5535audio/
 
 CX18 VIDEO4LINUX DRIVER
-M:     Andy Walls <awalls@radix.net>
+M:     Andy Walls <awalls@md.metrocast.net>
 L:     ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -2109,11 +2111,18 @@ F:      drivers/edac/i5000_edac.c
 
 EDAC-I5400
 M:     Mauro Carvalho Chehab <mchehab@redhat.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i5400_edac.c
 
+EDAC-I7CORE
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
+L:     linux-edac@vger.kernel.org
+W:     bluesmoke.sourceforge.net
+S:     Maintained
+F:     drivers/edac/i7core_edac.c linux/edac_mce.h drivers/edac/edac_mce.c
+
 EDAC-I82975X
 M:     Ranganathan Desikan <ravi@jetztechnologies.com>
 M:     "Arvind R." <arvind@jetztechnologies.com>
@@ -2887,6 +2896,13 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git
 S:     Maintained
 F:     drivers/input/
 
+INPUT MULTITOUCH (MT) PROTOCOL
+M:     Henrik Rydberg <rydberg@euromail.se>
+L:     linux-input@vger.kernel.org
+S:     Maintained
+F:     Documentation/input/multi-touch-protocol.txt
+K:     \b(ABS|SYN)_MT_
+
 INTEL IDLE DRIVER
 M:     Len Brown <lenb@kernel.org>
 L:     linux-pm@lists.linux-foundation.org
@@ -2978,22 +2994,14 @@ F:      drivers/net/ixgb/
 F:     drivers/net/ixgbe/
 
 INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
-M:     Zhu Yi <yi.zhu@intel.com>
-M:     Reinette Chatre <reinette.chatre@intel.com>
-M:     Intel Linux Wireless <ilw@linux.intel.com>
 L:     linux-wireless@vger.kernel.org
-W:     http://ipw2100.sourceforge.net
-S:     Odd Fixes
+S:     Orphan
 F:     Documentation/networking/README.ipw2100
 F:     drivers/net/wireless/ipw2x00/ipw2100.*
 
 INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
-M:     Zhu Yi <yi.zhu@intel.com>
-M:     Reinette Chatre <reinette.chatre@intel.com>
-M:     Intel Linux Wireless <ilw@linux.intel.com>
 L:     linux-wireless@vger.kernel.org
-W:     http://ipw2200.sourceforge.net
-S:     Odd Fixes
+S:     Orphan
 F:     Documentation/networking/README.ipw2200
 F:     drivers/net/wireless/ipw2x00/ipw2200.*
 
@@ -3019,8 +3027,8 @@ F:        drivers/net/wimax/i2400m/
 F:     include/linux/wimax/i2400m.h
 
 INTEL WIRELESS WIFI LINK (iwlwifi)
-M:     Zhu Yi <yi.zhu@intel.com>
 M:     Reinette Chatre <reinette.chatre@intel.com>
+M:     Wey-Yi Guy <wey-yi.w.guy@intel.com>
 M:     Intel Linux Wireless <ilw@linux.intel.com>
 L:     linux-wireless@vger.kernel.org
 W:     http://intellinuxwireless.org
@@ -3030,7 +3038,6 @@ F:        drivers/net/wireless/iwlwifi/
 
 INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
 M:     Samuel Ortiz <samuel.ortiz@intel.com>
-M:     Zhu Yi <yi.zhu@intel.com>
 M:     Intel Linux Wireless <ilw@linux.intel.com>
 L:     linux-wireless@vger.kernel.org
 S:     Supported
@@ -3165,7 +3172,7 @@ F:        Documentation/hwmon/it87
 F:     drivers/hwmon/it87.c
 
 IVTV VIDEO4LINUX DRIVER
-M:     Andy Walls <awalls@radix.net>
+M:     Andy Walls <awalls@md.metrocast.net>
 L:     ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -3242,7 +3249,7 @@ L:        autofs@linux.kernel.org
 S:     Maintained
 F:     fs/autofs4/
 
-KERNEL BUILD
+KERNEL BUILD + files below scripts/ (unless maintained elsewhere)
 M:     Michal Marek <mmarek@suse.cz>
 T:     git git://repo.or.cz/linux-kbuild.git for-next
 T:     git git://repo.or.cz/linux-kbuild.git for-linus
@@ -3251,6 +3258,9 @@ S:        Maintained
 F:     Documentation/kbuild/
 F:     Makefile
 F:     scripts/Makefile.*
+F:     scripts/basic/
+F:     scripts/mk*
+F:     scripts/package/
 
 KERNEL JANITORS
 L:     kernel-janitors@vger.kernel.org
@@ -3379,7 +3389,7 @@ KPROBES
 M:     Ananth N Mavinakayanahalli <ananth@in.ibm.com>
 M:     Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
 M:     "David S. Miller" <davem@davemloft.net>
-M:     Masami Hiramatsu <mhiramat@redhat.com>
+M:     Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
 S:     Maintained
 F:     Documentation/kprobes.txt
 F:     include/linux/kprobes.h
@@ -3500,9 +3510,8 @@ F:        arch/powerpc/platforms/83xx/
 
 LINUX FOR POWERPC PA SEMI PWRFICIENT
 M:     Olof Johansson <olof@lixom.net>
-W:     http://www.pasemi.com/
 L:     linuxppc-dev@ozlabs.org
-S:     Supported
+S:     Maintained
 F:     arch/powerpc/platforms/pasemi/
 F:     drivers/*/*pasemi*
 F:     drivers/*/*/*pasemi*
@@ -4213,6 +4222,7 @@ OPEN FIRMWARE AND FLATTENED DEVICE TREE
 M:     Grant Likely <grant.likely@secretlab.ca>
 L:     devicetree-discuss@lists.ozlabs.org
 W:     http://fdt.secretlab.ca
+T:     git git://git.secretlab.ca/git/linux-2.6.git
 S:     Maintained
 F:     drivers/of
 F:     include/linux/of*.h
@@ -4627,6 +4637,12 @@ M:       Robert Jarzmik <robert.jarzmik@free.fr>
 L:     rtc-linux@googlegroups.com
 S:     Maintained
 
+QLOGIC QLA1280 SCSI DRIVER
+M:     Michael Reed <mdr@sgi.com>
+L:     linux-scsi@vger.kernel.org
+S:     Maintained
+F:     drivers/scsi/qla1280.[ch]
+
 QLOGIC QLA2XXX FC-SCSI DRIVER
 M:     Andrew Vasquez <andrew.vasquez@qlogic.com>
 M:     linux-driver@qlogic.com
@@ -5385,6 +5401,7 @@ M:        David Brownell <dbrownell@users.sourceforge.net>
 M:     Grant Likely <grant.likely@secretlab.ca>
 L:     spi-devel-general@lists.sourceforge.net
 Q:     http://patchwork.kernel.org/project/spi-devel-general/list/
+T:     git git://git.secretlab.ca/git/linux-2.6.git
 S:     Maintained
 F:     Documentation/spi/
 F:     drivers/spi/
index 6e39ec701cbfd06565e765af97ca84bdba4f9809..015eca5a1f184a9cdf7148888fcdd28f2a21cd96 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 35
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc3
 NAME = Sheep on Meth
 
 # *DOCUMENTATION*
@@ -183,11 +183,14 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
 # CROSS_COMPILE can be set on the command line
 # make CROSS_COMPILE=ia64-linux-
 # Alternatively CROSS_COMPILE can be set in the environment.
+# A third alternative is to store a setting in .config so that plain
+# "make" in the configured kernel build directory always uses that.
 # Default value for CROSS_COMPILE is not to prefix executables
 # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
 export KBUILD_BUILDHOST := $(SUBARCH)
 ARCH           ?= $(SUBARCH)
 CROSS_COMPILE  ?=
+CROSS_COMPILE  ?= $(CONFIG_CROSS_COMPILE:"%"=%)
 
 # Architecture as present in compile.h
 UTS_MACHINE    := $(ARCH)
@@ -576,9 +579,6 @@ KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,)
 # disable invalid "can't wrap" optimizations for signed / pointers
 KBUILD_CFLAGS  += $(call cc-option,-fno-strict-overflow)
 
-# revert to pre-gcc-4.4 behaviour of .eh_frame
-KBUILD_CFLAGS  += $(call cc-option,-fno-dwarf2-cfi-asm)
-
 # conserve stack if available
 KBUILD_CFLAGS   += $(call cc-option,-fconserve-stack)
 
@@ -882,73 +882,11 @@ $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
 PHONY += $(vmlinux-dirs)
 $(vmlinux-dirs): prepare scripts
        $(Q)$(MAKE) $(build)=$@
-ifdef CONFIG_MODULES
-       $(Q)$(MAKE) $(modbuiltin)=$@
-endif
-
-# Build the kernel release string
-#
-# The KERNELRELEASE value built here is stored in the file
-# include/config/kernel.release, and is used when executing several
-# make targets, such as "make install" or "make modules_install."
-#
-# The eventual kernel release string consists of the following fields,
-# shown in a hierarchical format to show how smaller parts are concatenated
-# to form the larger and final value, with values coming from places like
-# the Makefile, kernel config options, make command line options and/or
-# SCM tag information.
-#
-#      $(KERNELVERSION)
-#        $(VERSION)                    eg, 2
-#        $(PATCHLEVEL)                 eg, 6
-#        $(SUBLEVEL)                   eg, 18
-#        $(EXTRAVERSION)               eg, -rc6
-#      $(localver-full)
-#        $(localver)
-#          localversion*               (files without backups, containing '~')
-#          $(CONFIG_LOCALVERSION)      (from kernel config setting)
-#        $(localver-auto)              (only if CONFIG_LOCALVERSION_AUTO is set)
-#          ./scripts/setlocalversion   (SCM tag, if one exists)
-#          $(LOCALVERSION)             (from make command line if provided)
-#
-#  Note how the final $(localver-auto) string is included *only* if the
-# kernel config option CONFIG_LOCALVERSION_AUTO is selected.  Also, at the
-# moment, only git is supported but other SCMs can edit the script
-# scripts/setlocalversion and add the appropriate checks as needed.
-
-pattern = ".*/localversion[^~]*"
-string  = $(shell cat /dev/null \
-          `find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort -u`)
-
-localver = $(subst $(space),, $(string) \
-                             $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
-
-# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
-# and if the SCM is know a tag from the SCM is appended.
-# The appended tag is determined by the SCM used.
-#
-# .scmversion is used when generating rpm packages so we do not loose
-# the version information from the SCM when we do the build of the kernel
-# from the copied source
-ifdef CONFIG_LOCALVERSION_AUTO
-
-ifeq ($(wildcard .scmversion),)
-        _localver-auto = $(shell $(CONFIG_SHELL) \
-                         $(srctree)/scripts/setlocalversion $(srctree))
-else
-        _localver-auto = $(shell cat .scmversion 2> /dev/null)
-endif
-
-       localver-auto  = $(LOCALVERSION)$(_localver-auto)
-endif
-
-localver-full = $(localver)$(localver-auto)
 
 # Store (new) KERNELRELASE string in include/config/kernel.release
-kernelrelease = $(KERNELVERSION)$(localver-full)
 include/config/kernel.release: include/config/auto.conf FORCE
        $(Q)rm -f $@
-       $(Q)echo $(kernelrelease) > $@
+       $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) scripts/setlocalversion $(srctree))" > $@
 
 
 # Things we need to do before we recursively start building the kernel
@@ -1087,13 +1025,18 @@ all: modules
 #      using awk while concatenating to the final file.
 
 PHONY += modules
-modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
+modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
        $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
-       $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.builtin) > $(objtree)/modules.builtin
        @$(kecho) '  Building modules, stage 2.';
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
 
+modules.builtin: $(vmlinux-dirs:%=%/modules.builtin)
+       $(Q)$(AWK) '!x[$$0]++' $^ > $(objtree)/modules.builtin
+
+%/modules.builtin: include/config/auto.conf
+       $(Q)$(MAKE) $(modbuiltin)=$*
+
 
 # Target to prepare building external modules
 PHONY += modules_prepare
@@ -1247,7 +1190,9 @@ help:
        @echo  '  firmware_install- Install all firmware to INSTALL_FW_PATH'
        @echo  '                    (default: $$(INSTALL_MOD_PATH)/lib/firmware)'
        @echo  '  dir/            - Build all files in dir and below'
-       @echo  '  dir/file.[ois]  - Build specified target only'
+       @echo  '  dir/file.[oisS] - Build specified target only'
+       @echo  '  dir/file.lst    - Build specified mixed source/assembly target only'
+       @echo  '                    (requires a recent binutils and recent build (System.map))'
        @echo  '  dir/file.ko     - Build module including final link'
        @echo  '  modules_prepare - Set up for building external modules'
        @echo  '  tags/TAGS       - Generate tags file for editors'
index 1dce24bc455a7ff9a13495517c53743a142cd49d..adfab8a21dfe95714700580a58795da1f6f5d634 100644 (file)
@@ -410,7 +410,7 @@ static inline unsigned long __arch_hweight64(unsigned long w)
        return __kernel_ctpop(w);
 }
 
-static inline unsigned int __arch_weight32(unsigned int w)
+static inline unsigned int __arch_hweight32(unsigned int w)
 {
        return __arch_hweight64(w);
 }
index 7739a62440a7a7027e241385171827189f783dd8..5a62fb46ef20b60759db3c7fdb68dad4daf3e525 100644 (file)
@@ -35,7 +35,7 @@ endif
 
 obj-y   += irq_pyxis.o irq_i8259.o irq_srm.o
 obj-y   += err_ev6.o
-obj-y   += es1888.o smc37c669.o smc37c93x.o ns87312.o gct.o
+obj-y   += es1888.o smc37c669.o smc37c93x.o pc873xx.o gct.o
 obj-y    += srmcons.o
 
 else
@@ -63,11 +63,11 @@ obj-$(CONFIG_ALPHA_WILDFIRE)        += core_wildfire.o
 # Board support
 obj-$(CONFIG_ALPHA_ALCOR)      += sys_alcor.o irq_i8259.o irq_srm.o
 obj-$(CONFIG_ALPHA_CABRIOLET)  += sys_cabriolet.o irq_i8259.o irq_srm.o \
-                                  ns87312.o
+                                  pc873xx.o
 obj-$(CONFIG_ALPHA_EB164)      += sys_cabriolet.o irq_i8259.o irq_srm.o \
-                                  ns87312.o
+                                  pc873xx.o
 obj-$(CONFIG_ALPHA_EB66P)      += sys_cabriolet.o irq_i8259.o irq_srm.o \
-                                  ns87312.o
+                                  pc873xx.o
 obj-$(CONFIG_ALPHA_LX164)      += sys_cabriolet.o irq_i8259.o irq_srm.o \
                                   smc37c93x.o
 obj-$(CONFIG_ALPHA_PC164)      += sys_cabriolet.o irq_i8259.o irq_srm.o \
@@ -90,14 +90,14 @@ obj-$(CONFIG_ALPHA_RUFFIAN) += sys_ruffian.o irq_pyxis.o irq_i8259.o
 obj-$(CONFIG_ALPHA_RX164)      += sys_rx164.o irq_i8259.o
 obj-$(CONFIG_ALPHA_SABLE)      += sys_sable.o
 obj-$(CONFIG_ALPHA_LYNX)       += sys_sable.o
-obj-$(CONFIG_ALPHA_BOOK1)      += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
-obj-$(CONFIG_ALPHA_AVANTI)     += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
-obj-$(CONFIG_ALPHA_NONAME)     += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
-obj-$(CONFIG_ALPHA_P2K)                += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
-obj-$(CONFIG_ALPHA_XL)         += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
+obj-$(CONFIG_ALPHA_BOOK1)      += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o
+obj-$(CONFIG_ALPHA_AVANTI)     += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o
+obj-$(CONFIG_ALPHA_NONAME)     += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o
+obj-$(CONFIG_ALPHA_P2K)                += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o
+obj-$(CONFIG_ALPHA_XL)         += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o
 obj-$(CONFIG_ALPHA_SX164)      += sys_sx164.o irq_pyxis.o irq_i8259.o \
                                   irq_srm.o smc37c669.o
-obj-$(CONFIG_ALPHA_TAKARA)     += sys_takara.o irq_i8259.o ns87312.o
+obj-$(CONFIG_ALPHA_TAKARA)     += sys_takara.o irq_i8259.o pc873xx.o
 obj-$(CONFIG_ALPHA_WILDFIRE)   += sys_wildfire.o irq_i8259.o
 
 # Error support
diff --git a/arch/alpha/kernel/ns87312.c b/arch/alpha/kernel/ns87312.c
deleted file mode 100644 (file)
index 342b56d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *     linux/arch/alpha/kernel/ns87312.c
- */
-
-#include <linux/init.h>
-#include <asm/io.h>
-#include "proto.h"
-
-
-/*
- * The SRM console *disables* the IDE interface, this code ensures it's
- * enabled.
- *
- * This code bangs on a control register of the 87312 Super I/O chip
- * that implements parallel port/serial ports/IDE/FDI.  Depending on
- * the motherboard, the Super I/O chip can be configured through a
- * pair of registers that are located either at I/O ports 0x26e/0x26f
- * or 0x398/0x399.  Unfortunately, autodetecting which base address is
- * in use works only once (right after a reset).  The Super I/O chip
- * has the additional quirk that configuration register data must be
- * written twice (I believe this is a safety feature to prevent
- * accidental modification---fun, isn't it?).
- */
-
-void __init
-ns87312_enable_ide(long ide_base)
-{
-       int data;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       outb(0, ide_base);              /* set the index register for reg #0 */
-       data = inb(ide_base+1);         /* read the current contents */
-       outb(0, ide_base);              /* set the index register for reg #0 */
-       outb(data | 0x40, ide_base+1);  /* turn on IDE */
-       outb(data | 0x40, ide_base+1);  /* turn on IDE, really! */
-       local_irq_restore(flags);
-}
diff --git a/arch/alpha/kernel/pc873xx.c b/arch/alpha/kernel/pc873xx.c
new file mode 100644 (file)
index 0000000..27dcbff
--- /dev/null
@@ -0,0 +1,88 @@
+#include <linux/ioport.h>
+#include <asm/io.h>
+
+#include "pc873xx.h"
+
+static unsigned pc873xx_probelist[] = {0x398, 0x26e, 0};
+
+static char *pc873xx_names[] = {
+       "PC87303", "PC87306", "PC87312", "PC87332", "PC87334"
+};
+
+static unsigned int base, model;
+
+
+unsigned int __init pc873xx_get_base()
+{
+       return base;
+}
+
+char *__init pc873xx_get_model()
+{
+       return pc873xx_names[model];
+}
+
+static unsigned char __init pc873xx_read(unsigned int base, int reg)
+{
+       outb(reg, base);
+       return inb(base + 1);
+}
+
+static void __init pc873xx_write(unsigned int base, int reg, unsigned char data)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       outb(reg, base);
+       outb(data, base + 1);
+       outb(data, base + 1);           /* Must be written twice */
+       local_irq_restore(flags);
+}
+
+int __init pc873xx_probe(void)
+{
+       int val, index = 0;
+
+       while ((base = pc873xx_probelist[index++])) {
+
+               if (request_region(base, 2, "Super IO PC873xx") == NULL)
+                       continue;
+
+               val = pc873xx_read(base, REG_SID);
+               if ((val & 0xf0) == 0x10) {
+                       model = PC87332;
+                       break;
+               } else if ((val & 0xf8) == 0x70) {
+                       model = PC87306;
+                       break;
+               } else if ((val & 0xf8) == 0x50) {
+                       model = PC87334;
+                       break;
+               } else if ((val & 0xf8) == 0x40) {
+                       model = PC87303;
+                       break;
+               }
+
+               release_region(base, 2);
+       }
+
+       return (base == 0) ? -1 : 1;
+}
+
+void __init pc873xx_enable_epp19(void)
+{
+       unsigned char data;
+
+       printk(KERN_INFO "PC873xx enabling EPP v1.9\n");
+       data = pc873xx_read(base, REG_PCR);
+       pc873xx_write(base, REG_PCR, (data & 0xFC) | 0x02);
+}
+
+void __init pc873xx_enable_ide(void)
+{
+       unsigned char data;
+
+       printk(KERN_INFO "PC873xx enabling IDE interrupt\n");
+       data = pc873xx_read(base, REG_FER);
+       pc873xx_write(base, REG_FER, data | 0x40);
+}
diff --git a/arch/alpha/kernel/pc873xx.h b/arch/alpha/kernel/pc873xx.h
new file mode 100644 (file)
index 0000000..25e1695
--- /dev/null
@@ -0,0 +1,35 @@
+
+#ifndef _PC873xx_H_
+#define _PC873xx_H_
+
+/*
+ * Control Register Values
+ */
+#define REG_FER        0x00
+#define REG_FAR        0x01
+#define REG_PTR        0x02
+#define REG_FCR        0x03
+#define REG_PCR        0x04
+#define REG_KRR        0x05
+#define REG_PMC        0x06
+#define REG_TUP        0x07
+#define REG_SID        0x08
+#define REG_ASC        0x09
+#define REG_IRC        0x0e
+
+/*
+ * Model numbers
+ */
+#define PC87303        0
+#define PC87306        1
+#define PC87312        2
+#define PC87332        3
+#define PC87334        4
+
+int pc873xx_probe(void);
+unsigned int pc873xx_get_base(void);
+char *pc873xx_get_model(void);
+void pc873xx_enable_epp19(void);
+void pc873xx_enable_ide(void);
+
+#endif
index a5fffc882c72f78429545cea81d5575ec16d11f2..738fc824e2ea373f85b3ae04fb7eb1346ecacdac 100644 (file)
@@ -53,7 +53,6 @@ static int __pci_mmap_fits(struct pci_dev *pdev, int num,
 
 /**
  * pci_mmap_resource - map a PCI resource into user memory space
- * @filp: open sysfs file
  * @kobj: kobject for mapping
  * @attr: struct bin_attribute for the file being mapped
  * @vma: struct vm_area_struct passed into the mmap
@@ -61,7 +60,7 @@ static int __pci_mmap_fits(struct pci_dev *pdev, int num,
  *
  * Use the bus mapping routines to map a PCI resource into userspace.
  */
-static int pci_mmap_resource(struct file *filp, struct kobject *kobj,
+static int pci_mmap_resource(struct kobject *kobj,
                             struct bin_attribute *attr,
                             struct vm_area_struct *vma, int sparse)
 {
index d4327e461c22156543e044eff59abc1ba628e0ad..85b4aea01ef8bcfee02fdcae4ddd9bd44d0cc91d 100644 (file)
@@ -34,6 +34,7 @@
 #include "irq_impl.h"
 #include "pci_impl.h"
 #include "machvec_impl.h"
+#include "pc873xx.h"
 
 #if defined(ALPHA_RESTORE_SRM_SETUP)
 /* Save LCA configuration data as the console had it set up.  */
@@ -208,7 +209,27 @@ noname_init_pci(void)
        common_init_pci();
        sio_pci_route();
        sio_fixup_irq_levels(sio_collect_irq_levels());
-       ns87312_enable_ide(0x26e);
+
+       if (pc873xx_probe() == -1) {
+               printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n");
+       } else {
+               printk(KERN_INFO "Found %s Super IO chip at 0x%x\n",
+                       pc873xx_get_model(), pc873xx_get_base());
+
+               /* Enabling things in the Super IO chip doesn't actually
+                * configure and enable things, the legacy drivers still
+                * need to do the actual configuration and enabling.
+                * This only unblocks them.
+                */
+
+#if !defined(CONFIG_ALPHA_AVANTI)
+               /* Don't bother on the Avanti family.
+                * None of them had on-board IDE.
+                */
+               pc873xx_enable_ide();
+#endif
+               pc873xx_enable_epp19();
+       }
 }
 
 static inline void __init
index a52a27c1d9be16f6eafb055a3bc95663b1ec6ce3..6f80665f477e70b0acad4d6ead228295446863c3 100644 (file)
@@ -951,8 +951,6 @@ static int sa1111_resume(struct platform_device *dev)
        if (!save)
                return 0;
 
-       spin_lock_irqsave(&sachip->lock, flags);
-
        /*
         * Ensure that the SA1111 is still here.
         * FIXME: shouldn't do this here.
@@ -969,6 +967,13 @@ static int sa1111_resume(struct platform_device *dev)
         * First of all, wake up the chip.
         */
        sa1111_wake(sachip);
+
+       /*
+        * Only lock for write ops. Also, sa1111_wake must be called with
+        * released spinlock!
+        */
+       spin_lock_irqsave(&sachip->lock, flags);
+
        sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
        sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
 
index d029d1f5f9e2c16343d9650afe4190531d1b635d..02cae5e2951c2d8ebc6cade2c582d5bb37d25d54 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
+#include <linux/completion.h>
 #include <mach/dma.h>
 
 #define MSM_DMOV_CHANNEL_COUNT 16
index 2c471fc451d743a590bd22c9cbdd07a985191c1d..f035f4185274160757e11d32377509defbdfb1b7 100644 (file)
@@ -32,7 +32,10 @@ void clk_disable(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_disable);
 
-/* We have a fixed clock alone, for now */
+static struct clk clk_24 = {
+       .rate = 2400000,
+};
+
 static struct clk clk_48 = {
        .rate = 48 * 1000 * 1000,
 };
@@ -50,6 +53,8 @@ static struct clk clk_default;
        }
 
 static struct clk_lookup lookups[] = {
+       CLK(&clk_24, "mtu0"),
+       CLK(&clk_24, "mtu1"),
        CLK(&clk_48, "uart0"),
        CLK(&clk_48, "uart1"),
        CLK(&clk_default, "gpio.0"),
@@ -59,10 +64,8 @@ static struct clk_lookup lookups[] = {
        CLK(&clk_default, "rng"),
 };
 
-static int __init clk_init(void)
+int __init clk_init(void)
 {
        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
        return 0;
 }
-
-arch_initcall(clk_init);
index 5563985a2cc7debf405729fffa1ca82899d87598..78da2e7c3985041cec5de8a5f3a536ca08e9373e 100644 (file)
@@ -11,3 +11,5 @@
 struct clk {
        unsigned long           rate;
 };
+
+int __init clk_init(void);
index 91c3c901b469619a7fc58fb163114b62bd9696e8..ac58e3b03b1a5516e87379450ccffcd9dd4a1fb7 100644 (file)
@@ -31,6 +31,8 @@
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
 
+#include "clock.h"
+
 #define __MEM_4K_RESOURCE(x) \
        .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM}
 
@@ -143,6 +145,12 @@ void __init cpu8815_init_irq(void)
        /* This modified VIC cell has two register blocks, at 0 and 0x20 */
        vic_init(io_p2v(NOMADIK_IC_BASE + 0x00), IRQ_VIC_START +  0, ~0, 0);
        vic_init(io_p2v(NOMADIK_IC_BASE + 0x20), IRQ_VIC_START + 32, ~0, 0);
+
+       /*
+        * Init clocks here so that they are available for system timer
+        * initialization.
+        */
+       clk_init();
 }
 
 /*
index f848ba8dbc16916d82ec3c6cae2a436d7c849265..a04cffd691c55995812365aa78c373e7950d0b2c 100644 (file)
@@ -538,9 +538,7 @@ static void ads7846_dev_init(void)
                printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
 
        gpio_direction_input(OMAP3_STALKER_TS_GPIO);
-
-       omap_set_gpio_debounce(OMAP3_STALKER_TS_GPIO, 1);
-       omap_set_gpio_debounce_time(OMAP3_STALKER_TS_GPIO, 0xa);
+       gpio_set_debounce(OMAP3_STALKER_TS_GPIO, 310);
 }
 
 static int ads7846_get_pendown_state(void)
index 02804224517b26abb7460f1ebd98ff5c266e0dea..e10db7a90cb270f5f833cd1b9076bd7b6cb38356 100644 (file)
@@ -1369,6 +1369,7 @@ static struct clk emif1_ick = {
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .flags          = ENABLE_ON_INIT,
        .clkdm_name     = "l3_emif_clkdm",
        .parent         = &ddrphy_ck,
        .recalc         = &followparent_recalc,
@@ -1379,6 +1380,7 @@ static struct clk emif2_ick = {
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .flags          = ENABLE_ON_INIT,
        .clkdm_name     = "l3_emif_clkdm",
        .parent         = &ddrphy_ck,
        .recalc         = &followparent_recalc,
index 95c9a5f774e13f1d123bd2a0968dd418e92bafd4..b7a4133267d80b73cd0ff59fe8d339efae649839 100644 (file)
@@ -409,10 +409,11 @@ static int _init_main_clk(struct omap_hwmod *oh)
                return 0;
 
        oh->_clk = omap_clk_get_by_name(oh->main_clk);
-       if (!oh->_clk)
+       if (!oh->_clk) {
                pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n",
                           oh->name, oh->main_clk);
                return -EINVAL;
+       }
 
        if (!oh->_clk->clkdm)
                pr_warning("omap_hwmod: %s: missing clockdomain for %s.\n",
@@ -444,10 +445,11 @@ static int _init_interface_clks(struct omap_hwmod *oh)
                        continue;
 
                c = omap_clk_get_by_name(os->clk);
-               if (!c)
+               if (!c) {
                        pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
                                   oh->name, os->clk);
                        ret = -EINVAL;
+               }
                os->_clk = c;
        }
 
@@ -470,10 +472,11 @@ static int _init_opt_clks(struct omap_hwmod *oh)
 
        for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) {
                c = omap_clk_get_by_name(oc->clk);
-               if (!c)
+               if (!c) {
                        pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
                                   oh->name, oc->clk);
                        ret = -EINVAL;
+               }
                oc->_clk = c;
        }
 
index 2e967716cc3fd27bb368951b6ee0599897b2b490..b88737fd6cfe7a434f6254e81dad7f90d8e3cd1a 100644 (file)
@@ -99,7 +99,7 @@ static void omap3_enable_io_chain(void)
                /* Do a readback to assure write has been done */
                prm_read_mod_reg(WKUP_MOD, PM_WKEN);
 
-               while (!(prm_read_mod_reg(WKUP_MOD, PM_WKST) &
+               while (!(prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
                         OMAP3430_ST_IO_CHAIN_MASK)) {
                        timeout++;
                        if (timeout > 1000) {
@@ -108,7 +108,7 @@ static void omap3_enable_io_chain(void)
                                return;
                        }
                        prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
-                                            WKUP_MOD, PM_WKST);
+                                            WKUP_MOD, PM_WKEN);
                }
        }
 }
index c68f799e83c57bb53fb20c10fb0610fdbc53e8fc..d72d1ac303338e23bed5abe38392e9aed6e0183b 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
+
 #include <asm/io.h>
 #include <plat/mux.h>
 
index 033b567e50bbd372e37defbd1764943cd09cfa73..ce1104d1bc17862834f92473cbe304070e996457 100644 (file)
@@ -263,11 +263,11 @@ const struct matrix_keymap_data palmtc_keymap_data = {
        .keymap_size            = ARRAY_SIZE(palmtc_matrix_keys),
 };
 
-const static unsigned int palmtc_keypad_row_gpios[] = {
+static const unsigned int palmtc_keypad_row_gpios[] = {
        0, 9, 10, 11
 };
 
-const static unsigned int palmtc_keypad_col_gpios[] = {
+static const unsigned int palmtc_keypad_col_gpios[] = {
        18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 79, 80
 };
 
index 4d2413ed0ffa57b72c9c2b732c1d182f016a756e..c1048a35f187e990984a83111110671241ff1f93 100644 (file)
@@ -818,6 +818,9 @@ static struct i2c_board_info akita_i2c_board_info[] = {
                .type           = "max7310",
                .addr           = 0x18,
                .platform_data  = &akita_ioexp,
+       }, {
+               .type           = "wm8750",
+               .addr           = 0x1b,
        },
 };
 
index c7bc4199e3a8691e3a8e180d5291e556e79dd8cd..4556aea9c3c5acfcd1aa9ed860dffcd9e06cabaf 100644 (file)
@@ -7,4 +7,5 @@ obj-$(CONFIG_UX500_SOC_DB5500)  += cpu-db5500.o devices-db5500.o
 obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
 obj-$(CONFIG_MACH_U8500_MOP)   += board-mop500.o
 obj-$(CONFIG_MACH_U5500)       += board-u5500.o
-obj-$(CONFIG_SMP)              += platsmp.o headsmp.o localtimer.o
+obj-$(CONFIG_SMP)              += platsmp.o headsmp.o
+obj-$(CONFIG_LOCAL_TIMERS)     += localtimer.o
index 6544855af2f169d8fe31af7bf140f11e765c701c..fe84b9021c7adee213fdb94c7639c7f77e2dfaa5 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <asm/clkdev.h>
 
+#include <plat/mtu.h>
 #include <mach/hardware.h>
 #include "clock.h"
 
@@ -59,6 +60,9 @@
 #define PRCM_DMACLK_MGT                0x074
 #define PRCM_B2R2CLK_MGT       0x078
 #define PRCM_TVCLK_MGT         0x07C
+#define PRCM_TCR               0x1C8
+#define PRCM_TCR_STOPPED       (1 << 16)
+#define PRCM_TCR_DOZE_MODE     (1 << 17)
 #define PRCM_UNIPROCLK_MGT     0x278
 #define PRCM_SSPCLK_MGT                0x280
 #define PRCM_RNGCLK_MGT                0x284
@@ -120,10 +124,95 @@ void clk_disable(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_disable);
 
+/*
+ * The MTU has a separate, rather complex muxing setup
+ * with alternative parents (peripheral cluster or
+ * ULP or fixed 32768 Hz) depending on settings
+ */
+static unsigned long clk_mtu_get_rate(struct clk *clk)
+{
+       void __iomem *addr = __io_address(U8500_PRCMU_BASE)
+               + PRCM_TCR;
+       u32 tcr = readl(addr);
+       int mtu = (int) clk->data;
+       /*
+        * One of these is selected eventually
+        * TODO: Replace the constant with a reference
+        * to the ULP source once this is modeled.
+        */
+       unsigned long clk32k = 32768;
+       unsigned long mturate;
+       unsigned long retclk;
+
+       /* Get the rate from the parent as a default */
+       if (clk->parent_periph)
+               mturate = clk_get_rate(clk->parent_periph);
+       else if (clk->parent_cluster)
+               mturate = clk_get_rate(clk->parent_cluster);
+       else
+               /* We need to be connected SOMEWHERE */
+               BUG();
+
+       /*
+        * Are we in doze mode?
+        * In this mode the parent peripheral or the fixed 32768 Hz
+        * clock is fed into the block.
+        */
+       if (!(tcr & PRCM_TCR_DOZE_MODE)) {
+               /*
+                * Here we're using the clock input from the APE ULP
+                * clock domain. But first: are the timers stopped?
+                */
+               if (tcr & PRCM_TCR_STOPPED) {
+                       clk32k = 0;
+                       mturate = 0;
+               } else {
+                       /* Else default mode: 0 and 2.4 MHz */
+                       clk32k = 0;
+                       if (cpu_is_u5500())
+                               /* DB5500 divides by 8 */
+                               mturate /= 8;
+                       else if (cpu_is_u8500ed()) {
+                               /*
+                                * This clocking setting must not be used
+                                * in the ED chip, it is simply not
+                                * connected anywhere!
+                                */
+                               mturate = 0;
+                               BUG();
+                       } else
+                               /*
+                                * In this mode the ulp38m4 clock is divided
+                                * by a factor 16, on the DB8500 typically
+                                * 38400000 / 16 ~ 2.4 MHz.
+                                * TODO: Replace the constant with a reference
+                                * to the ULP source once this is modeled.
+                                */
+                               mturate = 38400000 / 16;
+               }
+       }
+
+       /* Return the clock selected for this MTU */
+       if (tcr & (1 << mtu))
+               retclk = clk32k;
+       else
+               retclk = mturate;
+
+       pr_info("MTU%d clock rate: %lu Hz\n", mtu, retclk);
+       return retclk;
+}
+
 unsigned long clk_get_rate(struct clk *clk)
 {
        unsigned long rate;
 
+       /*
+        * If there is a custom getrate callback for this clock,
+        * it will take precedence.
+        */
+       if (clk->get_rate)
+               return clk->get_rate(clk);
+
        if (clk->ops && clk->ops->get_rate)
                return clk->ops->get_rate(clk);
 
@@ -341,8 +430,9 @@ static DEFINE_PRCC_CLK(5, usb_v1,   0,  0, NULL);
 
 /* Peripheral Cluster #6 */
 
-static DEFINE_PRCC_CLK(6, mtu1_v1,     8, -1, NULL);
-static DEFINE_PRCC_CLK(6, mtu0_v1,     7, -1, NULL);
+/* MTU ID in data */
+static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1);
+static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0);
 static DEFINE_PRCC_CLK(6, cfgreg_v1,   6,  6, NULL);
 static DEFINE_PRCC_CLK(6, dmc_ed,      6,  6, NULL);
 static DEFINE_PRCC_CLK(6, hash1,       5, -1, NULL);
@@ -357,8 +447,9 @@ static DEFINE_PRCC_CLK(6, rng_v1,   0,  0, &clk_rngclk);
 /* Peripheral Cluster #7 */
 
 static DEFINE_PRCC_CLK(7, tzpc0_ed,    4, -1, NULL);
-static DEFINE_PRCC_CLK(7, mtu1_ed,     3, -1, NULL);
-static DEFINE_PRCC_CLK(7, mtu0_ed,     2, -1, NULL);
+/* MTU ID in data */
+static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1);
+static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0);
 static DEFINE_PRCC_CLK(7, wdg_ed,      1, -1, NULL);
 static DEFINE_PRCC_CLK(7, cfgreg_ed,   0, -1, NULL);
 
@@ -503,15 +594,17 @@ static struct clk_lookup u8500_v1_clks[] = {
        CLK(uiccclk,    "uicc",         NULL),
 };
 
-static int __init clk_init(void)
+int __init clk_init(void)
 {
        if (cpu_is_u8500ed()) {
                clk_prcmu_ops.enable = clk_prcmu_ed_enable;
                clk_prcmu_ops.disable = clk_prcmu_ed_disable;
+               clk_per6clk.rate = 100000000;
        } else if (cpu_is_u5500()) {
                /* Clock tree for U5500 not implemented yet */
                clk_prcc_ops.enable = clk_prcc_ops.disable = NULL;
                clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL;
+               clk_per6clk.rate = 26000000;
        }
 
        clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
@@ -522,4 +615,3 @@ static int __init clk_init(void)
 
        return 0;
 }
-arch_initcall(clk_init);
index e4f99b65026f7787f863c53ca5c4e09a017ffa45..a058025015273f81b20cc6cd34a46255811e744a 100644 (file)
@@ -28,6 +28,9 @@ struct clkops {
  * @ops:               pointer to clkops struct used to control this clock
  * @name:              name, for debugging
  * @enabled:           refcount. positive if enabled, zero if disabled
+ * @get_rate:          custom callback for getting the clock rate
+ * @data:              custom per-clock data for example for the get_rate
+ *                     callback
  * @rate:              fixed rate for clocks which don't implement
  *                     ops->getrate
  * @prcmu_cg_off:      address offset of the combined enable/disable register
@@ -67,6 +70,8 @@ struct clk {
        const struct clkops     *ops;
        const char              *name;
        unsigned int            enabled;
+       unsigned long           (*get_rate)(struct clk *);
+       void                    *data;
 
        unsigned long           rate;
        struct list_head        list;
@@ -117,9 +122,26 @@ struct clk clk_##_name = {                                         \
                .parent_periph  = _kernclk                              \
        }
 
+#define DEFINE_PRCC_CLK_CUSTOM(_pclust, _name, _bus_en, _kernel_en, _kernclk, _callback, _data) \
+struct clk clk_##_name = {                                             \
+               .name           = #_name,                               \
+               .ops            = &clk_prcc_ops,                        \
+               .cluster        = _pclust,                              \
+               .prcc_bus       = _bus_en,                              \
+               .prcc_kernel    = _kernel_en,                           \
+               .parent_cluster = &clk_per##_pclust##clk,               \
+               .parent_periph  = _kernclk,                             \
+               .get_rate       = _callback,                            \
+               .data           = (void *) _data                        \
+       }
+
+
 #define CLK(_clk, _devname, _conname)                  \
        {                                               \
                .clk    = &clk_##_clk,                  \
                .dev_id = _devname,                     \
                .con_id = _conname,                     \
        }
+
+int __init clk_db8500_ed_fixup(void);
+int __init clk_init(void);
index d81ad023963c74dbb1ea8998cd9ed541cae5da8e..e0fd747e447ad6e3e299e57aadcfcfbcd4241867 100644 (file)
@@ -62,6 +62,12 @@ void __init ux500_init_irq(void)
 {
        gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
        gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+
+       /*
+        * Init clocks here so that they are available for system timer
+        * initialization.
+        */
+       clk_init();
 }
 
 #ifdef CONFIG_CACHE_L2X0
index e6f73030d5f0109cf147b581fd4c0b0885d77cb1..9b11eedba65fc4163cb33929addc2bf4e6784cbf 100644 (file)
@@ -2,6 +2,7 @@
  * Versatile Express Core Tile Cortex A9x4 Support
  */
 #include <linux/init.h>
+#include <linux/gfp.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
index 5eb4fd93893dfa113cddf7944eeb063d968965a2..ac163de7dc015f5c02c305d450f18151fdecc795 100644 (file)
@@ -18,7 +18,7 @@ feroceon_copy_user_page(void *kto, const void *kfrom)
 {
        asm("\
        stmfd   sp!, {r4-r9, lr}                \n\
-       mov     ip, %0                          \n\
+       mov     ip, %2                          \n\
 1:     mov     lr, r1                          \n\
        ldmia   r1!, {r2 - r9}                  \n\
        pld     [lr, #32]                       \n\
@@ -64,7 +64,7 @@ feroceon_copy_user_page(void *kto, const void *kfrom)
        mcr     p15, 0, ip, c7, c10, 4          @ drain WB\n\
        ldmfd   sp!, {r4-r9, pc}"
        :
-       : "I" (PAGE_SIZE));
+       : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE));
 }
 
 void feroceon_copy_user_highpage(struct page *to, struct page *from,
index 7c2eb55cd4a9263c9d3eb3e17d590cac0cc5d9b3..cb589cbb2b6c0322b1cdd61faf72a602db04a72e 100644 (file)
@@ -27,7 +27,7 @@ v4wb_copy_user_page(void *kto, const void *kfrom)
 {
        asm("\
        stmfd   sp!, {r4, lr}                   @ 2\n\
-       mov     r2, %0                          @ 1\n\
+       mov     r2, %2                          @ 1\n\
        ldmia   r1!, {r3, r4, ip, lr}           @ 4\n\
 1:     mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line\n\
        stmia   r0!, {r3, r4, ip, lr}           @ 4\n\
@@ -44,7 +44,7 @@ v4wb_copy_user_page(void *kto, const void *kfrom)
        mcr     p15, 0, r1, c7, c10, 4          @ 1   drain WB\n\
        ldmfd    sp!, {r4, pc}                  @ 3"
        :
-       : "I" (PAGE_SIZE / 64));
+       : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64));
 }
 
 void v4wb_copy_user_highpage(struct page *to, struct page *from,
index 172e6a55458eb321dbf0708be20433a4daa7909f..30c7d048a324b975535aef82062ea20f582793ed 100644 (file)
@@ -25,7 +25,7 @@ v4wt_copy_user_page(void *kto, const void *kfrom)
 {
        asm("\
        stmfd   sp!, {r4, lr}                   @ 2\n\
-       mov     r2, %0                          @ 1\n\
+       mov     r2, %2                          @ 1\n\
        ldmia   r1!, {r3, r4, ip, lr}           @ 4\n\
 1:     stmia   r0!, {r3, r4, ip, lr}           @ 4\n\
        ldmia   r1!, {r3, r4, ip, lr}           @ 4+1\n\
@@ -40,7 +40,7 @@ v4wt_copy_user_page(void *kto, const void *kfrom)
        mcr     p15, 0, r2, c7, c7, 0           @ flush ID cache\n\
        ldmfd   sp!, {r4, pc}                   @ 3"
        :
-       : "I" (PAGE_SIZE / 64));
+       : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64));
 }
 
 void v4wt_copy_user_highpage(struct page *to, struct page *from,
index 747ad4140fc75527d9c7b7409caf98e59504894d..f9cde0702f1eef3bbdb279462532865092f21152 100644 (file)
@@ -34,7 +34,7 @@ xsc3_mc_copy_user_page(void *kto, const void *kfrom)
 {
        asm("\
        stmfd   sp!, {r4, r5, lr}               \n\
-       mov     lr, %0                          \n\
+       mov     lr, %2                          \n\
                                                \n\
        pld     [r1, #0]                        \n\
        pld     [r1, #32]                       \n\
@@ -67,7 +67,7 @@ xsc3_mc_copy_user_page(void *kto, const void *kfrom)
                                                \n\
        ldmfd   sp!, {r4, r5, pc}"
        :
-       : "I" (PAGE_SIZE / 64 - 1));
+       : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64 - 1));
 }
 
 void xsc3_mc_copy_user_highpage(struct page *to, struct page *from,
index 92f5801f99c1d09c735fb586c9c44bc5df802f13..cbfb2edcf7d12a3a1cae18f04c041d94dc055bcc 100644 (file)
@@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
        if (addr < TASK_SIZE)
                return do_page_fault(addr, fsr, regs);
 
+       if (user_mode(regs))
+               goto bad_area;
+
        index = pgd_index(addr);
 
        /*
index 77b030f5ec09fa2dfbbcc562f345eb0ec04e3092..086816b205b8cf25c9d178c9d56c44a654e2ff9f 100644 (file)
@@ -48,7 +48,16 @@ void *kmap_atomic(struct page *page, enum km_type type)
 
        debug_kmap_atomic(type);
 
-       kmap = kmap_high_get(page);
+#ifdef CONFIG_DEBUG_HIGHMEM
+       /*
+        * There is no cache coherency issue when non VIVT, so force the
+        * dedicated kmap usage for better debugging purposes in that case.
+        */
+       if (!cache_is_vivt())
+               kmap = NULL;
+       else
+#endif
+               kmap = kmap_high_get(page);
        if (kmap)
                return kmap;
 
index 1ba6cf5a2c025b3dd22c84e0b190455e8c574ab3..f6a9994653237ddc2a56c7c1fbd9070615cea937 100644 (file)
@@ -678,10 +678,10 @@ void __init mem_init(void)
 void free_initmem(void)
 {
 #ifdef CONFIG_HAVE_TCM
-       extern char *__tcm_start, *__tcm_end;
+       extern char __tcm_start, __tcm_end;
 
-       totalram_pages += free_area(__phys_to_pfn(__pa(__tcm_start)),
-                                   __phys_to_pfn(__pa(__tcm_end)),
+       totalram_pages += free_area(__phys_to_pfn(__pa(&__tcm_start)),
+                                   __phys_to_pfn(__pa(&__tcm_end)),
                                    "TCM link");
 #endif
 
index 0ff3798769abb9a6fe2d03b390c5500c478b5141..08aaa4a7f65fe0e868b1a8cbfa8dd80d73209cec 100644 (file)
@@ -13,7 +13,9 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/clockchips.h>
+#include <linux/clk.h>
 #include <linux/jiffies.h>
+#include <linux/err.h>
 #include <asm/mach/time.h>
 
 #include <plat/mtu.h>
@@ -124,13 +126,25 @@ static struct irqaction nmdk_timer_irq = {
 void __init nmdk_timer_init(void)
 {
        unsigned long rate;
-       u32 cr = MTU_CRn_32BITS;;
+       struct clk *clk0;
+       struct clk *clk1;
+       u32 cr;
+
+       clk0 = clk_get_sys("mtu0", NULL);
+       BUG_ON(IS_ERR(clk0));
+
+       clk1 = clk_get_sys("mtu1", NULL);
+       BUG_ON(IS_ERR(clk1));
+
+       clk_enable(clk0);
+       clk_enable(clk1);
 
        /*
         * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500:
         * use a divide-by-16 counter if it's more than 16MHz
         */
-       rate = CLOCK_TICK_RATE;
+       cr = MTU_CRn_32BITS;;
+       rate = clk_get_rate(clk0);
        if (rate > 16 << 20) {
                rate /= 16;
                cr |= MTU_CRn_PRESCALE_16;
@@ -153,6 +167,14 @@ void __init nmdk_timer_init(void)
                       nmdk_clksrc.name);
 
        /* Timer 1 is used for events, fix according to rate */
+       cr = MTU_CRn_32BITS;
+       rate = clk_get_rate(clk1);
+       if (rate > 16 << 20) {
+               rate /= 16;
+               cr |= MTU_CRn_PRESCALE_16;
+       } else {
+               cr |= MTU_CRn_PRESCALE_1;
+       }
        writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */
        nmdk_clkevt.mult = div_sc(rate, NSEC_PER_SEC, nmdk_clkevt.shift);
        nmdk_clkevt.max_delta_ns =
index c64875f11fac9d937f79d5805d682bc0f4cb9bbe..44bafdab2dceaa94d7d6facbcfd422b2f65b660c 100644 (file)
@@ -541,11 +541,11 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
                  * timer is stopped
                  */
                udelay(3500000 / clk_get_rate(timer->fclk) + 1);
-               /* Ack possibly pending interrupt */
-               omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
-                               OMAP_TIMER_INT_OVERFLOW);
 #endif
        }
+       /* Ack possibly pending interrupt */
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
+                       OMAP_TIMER_INT_OVERFLOW);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
index 393e9219a5b68afe61f6416c3fac531cc188cefc..9b7e3545f32552e1cdb7d4bfc0b9cc6331de8b0f 100644 (file)
@@ -673,6 +673,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
                if (cpu_is_omap34xx() || cpu_is_omap44xx())
                        clk_disable(bank->dbck);
        }
+       bank->dbck_enable_mask = val;
 
        __raw_writel(val, reg);
 }
index e43983ba59c5eb77ac61caa3a2ebaca83b50416c..8ce0de247c71fc7b59863a6722036ef011238240 100644 (file)
@@ -140,8 +140,10 @@ static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags)
                return ERR_PTR(-ENOMEM);
 
        err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
-       if (err)
+       if (err) {
+               kfree(sgt);
                return ERR_PTR(err);
+       }
 
        pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
 
index 66dc2d03b7fc70c1130bd7b0a751dbeed6d53b17..d66cead97d28b3c5d63d9c22d4fdcb77b7d7bd8e 100644 (file)
@@ -277,7 +277,7 @@ ENTRY(vfp_put_double)
 #ifdef CONFIG_VFPv3
        @ d16 - d31 registers
        .irp    dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-1:     mcrr    p11, 3, r1, r2, c\dr    @ fmdrr r1, r2, d\dr
+1:     mcrr    p11, 3, r0, r1, c\dr    @ fmdrr r0, r1, d\dr
        mov     pc, lr
        .org    1b + 8
        .endr
index 77630df94343672e8b3aceeceb2b6f7416e05db5..884275629ef7405dfbbb901e0758fdc75594fd3e 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
+#include <linux/smp_lock.h>
 #include <linux/bcd.h>
 #include <linux/capability.h>
 
@@ -238,9 +239,7 @@ static unsigned char days_in_mo[] =
 
 /* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */
 
-static int
-rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-         unsigned long arg) 
+static int rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        unsigned long flags;
 
@@ -354,6 +353,17 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        }
 }
 
+static long rtc_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       int ret;
+
+       lock_kernel();
+       ret = rtc_ioctl(file, cmd, arg);
+       unlock_kernel();
+
+       return ret;
+}
+
 static void
 print_rtc_status(void)
 {
@@ -375,8 +385,8 @@ print_rtc_status(void)
 /* The various file operations we support. */
 
 static const struct file_operations rtc_fops = {
-       .owner =        THIS_MODULE,
-       .ioctl =        rtc_ioctl,
+       .owner          = THIS_MODULE,
+       .unlocked_ioctl = rtc_unlocked_ioctl,
 }; 
 
 /* Probe for the chip by writing something to its RAM and try reading it back. */
index 1e90c1a9c849bd4453b462e3b611808171e5c475..7dcb1f85f42b157c93eaaac921381e8ae163ca84 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/delay.h>
 #include <linux/bcd.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -53,7 +54,7 @@ static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
 static const unsigned char days_in_month[] =
        { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 
-int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+static long pcf8563_unlocked_ioctl(struct file *, unsigned int, unsigned long);
 
 /* Cache VL bit value read at driver init since writing the RTC_SECOND
  * register clears the VL status.
@@ -62,7 +63,7 @@ static int voltage_low;
 
 static const struct file_operations pcf8563_fops = {
        .owner = THIS_MODULE,
-       .ioctl = pcf8563_ioctl,
+       .unlocked_ioctl = pcf8563_unlocked_ioctl,
 };
 
 unsigned char
@@ -212,8 +213,7 @@ pcf8563_exit(void)
  * ioctl calls for this driver. Why return -ENOTTY upon error? Because
  * POSIX says so!
  */
-int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-       unsigned long arg)
+static int pcf8563_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        /* Some sanity checks. */
        if (_IOC_TYPE(cmd) != RTC_MAGIC)
@@ -339,6 +339,17 @@ int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        return 0;
 }
 
+static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       int ret;
+
+       lock_kernel();
+       return pcf8563_ioctl(filp, cmd, arg);
+       unlock_kernel();
+
+       return ret;
+}
+
 static int __init pcf8563_register(void)
 {
        if (pcf8563_init() < 0) {
index 1a61efc139826870b156eabc26987f9a3319852a..a0c0df8be9c8d966f34b026a078b4f150b6c4139 100644 (file)
@@ -17,8 +17,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
-#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
+#define crisv10_mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
+#define crisv10_unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
 
 /* don't use set_int_vector, it bypasses the linux interrupt handlers. it is
  * global just so that the kernel gdb can use it.
@@ -116,12 +116,12 @@ static unsigned int startup_crisv10_irq(unsigned int irq)
 
 static void enable_crisv10_irq(unsigned int irq)
 {
-       unmask_irq(irq);
+       crisv10_unmask_irq(irq);
 }
 
 static void disable_crisv10_irq(unsigned int irq)
 {
-       mask_irq(irq);
+       crisv10_mask_irq(irq);
 }
 
 static void ack_crisv10_irq(unsigned int irq)
index e5fb44f505c541f63950f162a933b979dcd00d20..49f5b8ca5b47bd595e78393914571c7442c756e2 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: dmacopy.c,v 1.1 2001/12/17 13:59:27 bjornw Exp $ 
- *
+/*
  * memcpy for large blocks, using memory-memory DMA channels 6 and 7 in Etrax
  */
 
@@ -13,11 +12,11 @@ void *dma_memcpy(void *pdst,
                 unsigned int pn)
 {
        static etrax_dma_descr indma, outdma;
-       
-       D(printk("dma_memcpy %d bytes... ", pn));
+
+       D(printk(KERN_DEBUG "dma_memcpy %d bytes... ", pn));
 
 #if 0
-       *R_GEN_CONFIG = genconfig_shadow = 
+       *R_GEN_CONFIG = genconfig_shadow =
                (genconfig_shadow & ~0x3c0000) |
                IO_STATE(R_GEN_CONFIG, dma6, intdma7) |
                IO_STATE(R_GEN_CONFIG, dma7, intdma6);
@@ -32,11 +31,11 @@ void *dma_memcpy(void *pdst,
        *R_DMA_CH7_FIRST = &outdma;
        *R_DMA_CH6_CMD = IO_STATE(R_DMA_CH6_CMD, cmd, start);
        *R_DMA_CH7_CMD = IO_STATE(R_DMA_CH7_CMD, cmd, start);
-       
-       while(*R_DMA_CH7_CMD == 1) /* wait for completion */ ;
 
-       D(printk("done\n"));
+       while (*R_DMA_CH7_CMD == 1)
+               /* wait for completion */;
 
+       D(printk(KERN_DEBUG "done\n"));
 }
 
 
index 56905aaa7b6e6b287bd3ad131833dd35903513fd..c09f19f478a586b04c252ca6d2ed43433cdaa049 100644 (file)
@@ -1,13 +1,11 @@
 /*
- * $Id: hw_settings.S,v 1.1 2001/12/17 13:59:27 bjornw Exp $
- * 
  * This table is used by some tools to extract hardware parameters.
  * The table should be included in the kernel and the decompressor.
  * Don't forget to update the tools if you change this table.
  *
  * Copyright (C) 2001 Axis Communications AB
  *
- * Authors:  Mikael Starvik (starvik@axis.com) 
+ * Authors:  Mikael Starvik (starvik@axis.com)
  */
 
 #define PA_SET_VALUE ((CONFIG_ETRAX_DEF_R_PORT_PA_DIR << 8) | \
 #define PB_SET_VALUE ((CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG << 16) | \
                (CONFIG_ETRAX_DEF_R_PORT_PB_DIR << 8) | \
                (CONFIG_ETRAX_DEF_R_PORT_PB_DATA))
-       
+
        .ascii "HW_PARAM_MAGIC" ; Magic number
        .dword 0xc0004000       ; Kernel start address
 
        ; Debug port
 #ifdef CONFIG_ETRAX_DEBUG_PORT0
-       .dword 0                
+       .dword 0
 #elif defined(CONFIG_ETRAX_DEBUG_PORT1)
        .dword 1
 #elif defined(CONFIG_ETRAX_DEBUG_PORT2)
@@ -30,7 +28,7 @@
        .dword 3
 #else
        .dword 4 ; No debug
-#endif                 
+#endif
 
        ; SDRAM or EDO DRAM?
 #ifdef CONFIG_ETRAX_SDRAM
@@ -39,7 +37,7 @@
        .dword 0
 #endif
 
-       ; Register values 
+       ; Register values
        .dword R_WAITSTATES
        .dword CONFIG_ETRAX_DEF_R_WAITSTATES
        .dword R_BUS_CONFIG
@@ -56,7 +54,7 @@
        .dword CONFIG_ETRAX_DEF_R_DRAM_TIMING
 #endif
        .dword R_PORT_PA_SET
-       .dword PA_SET_VALUE 
+       .dword PA_SET_VALUE
        .dword R_PORT_PB_SET
        .dword PB_SET_VALUE
        .dword 0 ; No more register values
index b9e328e688be8d70837d895698c4d87ee71e696f..a2dd740c5907868f54985a1176ea73df3d752c63 100644 (file)
@@ -360,24 +360,10 @@ config ETRAX_SER4_DSR_BIT
        string "Ser 4 DSR bit (empty = not used)"
        depends on ETRAX_SERIAL_PORT4
 
-config ETRAX_SER3_CD_BIT
+config ETRAX_SER4_CD_BIT
        string "Ser 4 CD bit (empty = not used)"
        depends on ETRAX_SERIAL_PORT4
 
-config ETRAX_RS485
-       bool "RS-485 support"
-       depends on ETRAXFS_SERIAL
-       help
-         Enables support for RS-485 serial communication.  For a primer on
-         RS-485, see <http://www.hw.cz/english/docs/rs485/rs485.html>.
-
-config ETRAX_RS485_DISABLE_RECEIVER
-       bool "Disable serial receiver"
-       depends on ETRAX_RS485
-       help
-         It is necessary to disable the serial receiver to avoid serial
-         loopback.  Not all products are able to do this in software only.
-
 config ETRAX_SYNCHRONOUS_SERIAL
        bool "Synchronous serial-port support"
        depends on ETRAX_ARCH_V32
index 506826399ae72edbcca777b79898a1c886475f59..2fd6a740d895ab2c1e1b2fe02fbf97857dccbdae 100644 (file)
@@ -649,10 +649,10 @@ i2c_release(struct inode *inode, struct file *filp)
 /* Main device API. ioctl's to write or read to/from i2c registers.
  */
 
-static int
-i2c_ioctl(struct inode *inode, struct file *file,
-         unsigned int cmd, unsigned long arg)
+static long
+i2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
+       int ret;
        if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) {
                return -ENOTTY;
        }
@@ -665,9 +665,13 @@ i2c_ioctl(struct inode *inode, struct file *file,
                                 I2C_ARGREG(arg),
                                 I2C_ARGVALUE(arg)));
 
-                       return i2c_writereg(I2C_ARGSLAVE(arg),
+                       lock_kernel();
+                       ret = i2c_writereg(I2C_ARGSLAVE(arg),
                                            I2C_ARGREG(arg),
                                            I2C_ARGVALUE(arg));
+                       unlock_kernel();
+                       return ret;
+
                case I2C_READREG:
                {
                        unsigned char val;
@@ -675,7 +679,9 @@ i2c_ioctl(struct inode *inode, struct file *file,
                        D(printk("i2cr %d %d ",
                                I2C_ARGSLAVE(arg),
                                I2C_ARGREG(arg)));
+                       lock_kernel();
                        val = i2c_readreg(I2C_ARGSLAVE(arg), I2C_ARGREG(arg));
+                       unlock_kernel();
                        D(printk("= %d\n", val));
                        return val;
                }
@@ -688,10 +694,10 @@ i2c_ioctl(struct inode *inode, struct file *file,
 }
 
 static const struct file_operations i2c_fops = {
-       .owner =    THIS_MODULE,
-       .ioctl =    i2c_ioctl,
-       .open =     i2c_open,
-       .release  i2c_release,
+       .owner          = THIS_MODULE,
+       .unlocked_ioctl = i2c_ioctl,
+       .open           = i2c_open,
+       .release        = i2c_release,
 };
 
 static int __init i2c_init(void)
index f4478506e52ca1df58b52180ffd871e77c51e726..bef6eb53b1539b9e6974b1e472aa638187e6ca6c 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
+#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/bcd.h>
 #include <linux/mutex.h>
@@ -49,7 +50,7 @@ static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
 static const unsigned char days_in_month[] =
        { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 
-int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 
 /* Cache VL bit value read at driver init since writing the RTC_SECOND
  * register clears the VL status.
@@ -57,8 +58,8 @@ int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 static int voltage_low;
 
 static const struct file_operations pcf8563_fops = {
-       .owner =        THIS_MODULE,
-       .ioctl =        pcf8563_ioctl
+       .owner          = THIS_MODULE,
+       .unlocked_ioctl = pcf8563_unlocked_ioctl,
 };
 
 unsigned char
@@ -208,8 +209,7 @@ pcf8563_exit(void)
  * ioctl calls for this driver. Why return -ENOTTY upon error? Because
  * POSIX says so!
  */
-int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-       unsigned long arg)
+static int pcf8563_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        /* Some sanity checks. */
        if (_IOC_TYPE(cmd) != RTC_MAGIC)
@@ -335,6 +335,17 @@ int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        return 0;
 }
 
+static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       int ret;
+
+       lock_kernel();
+       return pcf8563_ioctl(filp, cmd, arg);
+       unlock_kernel();
+
+       return ret;
+}
+
 static int __init pcf8563_register(void)
 {
        if (pcf8563_init() < 0) {
index 64933e2c0f5b88e4ead5e5d5f23bbb1c5421182a..bde8d1a10cadd31edb5b0120b0bc3feab73e07f9 100644 (file)
@@ -24,5 +24,5 @@ EXPORT_SYMBOL(crisv32_io_get_name);
 EXPORT_SYMBOL(crisv32_io_get);
 
 /* Functions masking/unmasking interrupts */
-EXPORT_SYMBOL(mask_irq);
-EXPORT_SYMBOL(unmask_irq);
+EXPORT_SYMBOL(crisv32_mask_irq);
+EXPORT_SYMBOL(crisv32_unmask_irq);
index b6241198fb98d86c72ab48999e40989fdf552411..0b1febe44aa3a5b61967253b2549b927cb5a1055 100644 (file)
@@ -280,8 +280,7 @@ out:
        return cpu;
 }
 
-void
-mask_irq(int irq)
+void crisv32_mask_irq(int irq)
 {
        int cpu;
 
@@ -289,8 +288,7 @@ mask_irq(int irq)
                block_irq(irq, cpu);
 }
 
-void
-unmask_irq(int irq)
+void crisv32_unmask_irq(int irq)
 {
        unblock_irq(irq, irq_cpu(irq));
 }
@@ -298,23 +296,23 @@ unmask_irq(int irq)
 
 static unsigned int startup_crisv32_irq(unsigned int irq)
 {
-       unmask_irq(irq);
+       crisv32_unmask_irq(irq);
        return 0;
 }
 
 static void shutdown_crisv32_irq(unsigned int irq)
 {
-       mask_irq(irq);
+       crisv32_mask_irq(irq);
 }
 
 static void enable_crisv32_irq(unsigned int irq)
 {
-       unmask_irq(irq);
+       crisv32_unmask_irq(irq);
 }
 
 static void disable_crisv32_irq(unsigned int irq)
 {
-       mask_irq(irq);
+       crisv32_mask_irq(irq);
 }
 
 static void ack_crisv32_irq(unsigned int irq)
index 058adddf4e4b1f39c981304cd2f3856f4edc850b..84fed3b4b0799dd35991e57eaa22aca18767c6a3 100644 (file)
@@ -168,8 +168,8 @@ void __init smp_callin(void)
 
        /* Enable IRQ and idle */
        REG_WR(intr_vect, irq_regs[cpu], rw_mask, vect_mask);
-       unmask_irq(IPI_INTR_VECT);
-       unmask_irq(TIMER0_INTR_VECT);
+       crisv32_unmask_irq(IPI_INTR_VECT);
+       crisv32_unmask_irq(TIMER0_INTR_VECT);
        preempt_disable();
        notify_cpu_starting(cpu);
        local_irq_enable();
index 6248004eca1c3b74b32e643e4b7e631e340179ba..7d345947b3ee271f0bc9d5206431d419d56f470c 100644 (file)
@@ -93,15 +93,16 @@ void set_break_vector(int n, irqvectptr addr);
   "push $r10\n\t"       /* push orig_r10 */ \
   "clear.d [$sp=$sp-4]\n\t"  /* frametype - this is a normal stackframe */
 
-  /* BLOCK_IRQ and UNBLOCK_IRQ do the same as mask_irq and unmask_irq */
+/* BLOCK_IRQ and UNBLOCK_IRQ do the same as
+ * crisv10_mask_irq and crisv10_unmask_irq */
 
 #define BLOCK_IRQ(mask,nr) \
   "move.d " #mask ",$r0\n\t" \
-  "move.d $r0,[0xb00000d8]\n\t" 
-  
+  "move.d $r0,[0xb00000d8]\n\t"
+
 #define UNBLOCK_IRQ(mask) \
   "move.d " #mask ",$r0\n\t" \
-  "move.d $r0,[0xb00000dc]\n\t" 
+  "move.d $r0,[0xb00000dc]\n\t"
 
 #define IRQ_NAME2(nr) nr##_interrupt(void)
 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
index 9e4c9fbdfddf63a905ad9e9c71bac6cbda6a8764..b31e9984f84964570b16e743892f4432af730269 100644 (file)
@@ -23,8 +23,8 @@ struct etrax_interrupt_vector {
 
 extern struct etrax_interrupt_vector *etrax_irv;       /* head.S */
 
-void mask_irq(int irq);
-void unmask_irq(int irq);
+void crisv32_mask_irq(int irq);
+void crisv32_unmask_irq(int irq);
 
 void set_exception_vector(int n, irqvectptr addr);
 
index 0e47994e40be536de84bcb6ed85a37770fb6015a..484fcf8667c01500fa46d71dcdbef0a7fce314f8 100644 (file)
@@ -2,22 +2,9 @@
 #define _ASMCRIS_PARAM_H
 
 /* Currently we assume that HZ=100 is good for CRIS. */
-#ifdef __KERNEL__
-# define HZ            CONFIG_HZ       /* Internal kernel timer frequency */
-# define USER_HZ       100             /* .. some user interfaces are in "ticks" */
-# define CLOCKS_PER_SEC        (USER_HZ)       /* like times() */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
 
 #define EXEC_PAGESIZE  8192
 
-#ifndef NOGROUP
-#define NOGROUP                (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64      /* max length of hostname */
+#include <asm-generic/param.h>
 
-#endif
+#endif /* _ASMCRIS_PARAM_H */
index bd0bdf908d937c58323f35fb8e7acb7897e2c0bf..cbb6958a31471f8348604822c74224f29511fb25 100644 (file)
@@ -21,7 +21,7 @@
 #
 # the break handler has its own stack
 #
-       .section        .bss.stack
+       .section        .bss..stack
        .globl          __break_user_context
        .balign         THREAD_SIZE
 __break_stack:
@@ -63,7 +63,7 @@ __break_trace_through_exceptions:
 # entry point for Break Exceptions/Interrupts
 #
 ###############################################################################
-       .section        .text.break
+       .section        .text..break
        .balign         4
        .globl          __entry_break
 __entry_break:
index 189397ec012aca45f87cc983ec414b18c9caf3bf..63d579bf1c2974d6cec4972af17ee1db812519c5 100644 (file)
@@ -38,7 +38,7 @@
 
 #define nr_syscalls ((syscall_table_size)/4)
 
-       .section        .text.entry
+       .section        .text..entry
        .balign         4
 
 .macro LEDS val
index 84d103c33c9c4356220725a853405ccf15ab8870..a4dba6b20bd0b8f4e2cd9582bd97c9a39a8453b7 100644 (file)
@@ -1789,6 +1789,12 @@ void gdbstub(int sigval)
                        flush_cache = 1;
                        break;
 
+                       /* pNN: Read value of reg N and return it */
+               case 'p':
+                       /* return no value, indicating that we don't support
+                        * this command and that gdb should use 'g' instead */
+                       break;
+
                        /* PNN,=RRRRRRRR: Write value R to reg N return OK */
                case 'P':
                        ptr = &input_buffer[1];
index b825ef3f2d548970e2d2745de5cf7c6165d5f70f..e9a8cc63ac9413a0233f6f55ec0d91693ee3cf57 100644 (file)
@@ -542,7 +542,7 @@ __head_end:
        .size           _boot, .-_boot
 
        # provide a point for GDB to place a break
-       .section        .text.start,"ax"
+       .section        .text..start,"ax"
        .globl          _start
        .balign         4
 _start:
index cbe811fccfcca0f2ef765a00c5924d2294ece358..8b973f3cc90e432ba2ac4a72dc602f5e4e5e3db3 100644 (file)
@@ -57,10 +57,10 @@ SECTIONS
   _text = .;
   _stext = .;
   .text : {
-       *(.text.start)
-       *(.text.entry)
-       *(.text.break)
-       *(.text.tlbmiss)
+       *(.text..start)
+       *(.text..entry)
+       *(.text..break)
+       *(.text..tlbmiss)
        TEXT_TEXT
        SCHED_TEXT
        LOCK_TEXT
@@ -114,7 +114,7 @@ SECTIONS
 
   .sbss                : { *(.sbss .sbss.*) }
   .bss         : { *(.bss .bss.*) }
-  .bss.stack   : { *(.bss) }
+  .bss..stack  : { *(.bss) }
 
   __bss_stop = .;
   _end = . ;
index 30f5d100a81c15038f79f88672db560cf4f950a5..a325d57a83d5fdae12d8323480564d8204e86117 100644 (file)
@@ -257,10 +257,10 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
  */
  out_of_memory:
        up_read(&mm->mmap_sem);
-       printk("VM: killing process %s\n", current->comm);
-       if (user_mode(__frame))
-               do_group_exit(SIGKILL);
-       goto no_context;
+       if (!user_mode(__frame))
+               goto no_context;
+       pagefault_out_of_memory();
+       return;
 
  do_sigbus:
        up_read(&mm->mmap_sem);
index 7f392bc651a358ad062dff38233f4f204d0dc4aa..f3ac019bb18bf401155d254d2cbcb6a426fbbf1a 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/pgtable.h>
 #include <asm/spr-regs.h>
 
-       .section        .text.tlbmiss
+       .section        .text..tlbmiss
        .balign         4
 
        .globl          __entry_insn_mmu_miss
index 985a81a2435a08715fc89a5fa6da5b322d041b90..10e9a2d1cc6c747586a2be624eec01849fd53c87 100644 (file)
@@ -9,7 +9,7 @@
 
 #define SRAM_START 0xff4000
 
-       .section        .text.startup
+       .section        .text..startup
        .global startup
 startup:
        mov.l   #SRAM_START+0x8000, sp
index 65e2a0d1ae396bd52e72f28270dcc935966675e5..a0a3a0ed54ef17450ae9dbe7f7a38e0789098fdd 100644 (file)
@@ -4,7 +4,7 @@ SECTIONS
         {
         __stext = . ;
        __text = .;
-              *(.text.startup)
+              *(.text..startup)
               *(.text)
         __etext = . ;
         }
index c1642fd640297b0796dec52172b80d8e0652f7dc..3ab6d75aa3dbdd68e59cc7dab789ab60ccd9d356 100644 (file)
@@ -70,12 +70,12 @@ name:
  * path (ivt.S - TLB miss processing) or in places where it might not be
  * safe to use a "tpa" instruction (mca_asm.S - error recovery).
  */
-       .section ".data.patch.vtop", "a"        // declare section & section attributes
+       .section ".data..patch.vtop", "a"       // declare section & section attributes
        .previous
 
 #define        LOAD_PHYSICAL(pr, reg, obj)             \
 [1:](pr)movl reg = obj;                                \
-       .xdata4 ".data.patch.vtop", 1b-.
+       .xdata4 ".data..patch.vtop", 1b-.
 
 /*
  * For now, we always put in the McKinley E9 workaround.  On CPUs that don't need it,
@@ -84,11 +84,11 @@ name:
 #define DO_MCKINLEY_E9_WORKAROUND
 
 #ifdef DO_MCKINLEY_E9_WORKAROUND
-       .section ".data.patch.mckinley_e9", "a"
+       .section ".data..patch.mckinley_e9", "a"
        .previous
 /* workaround for Itanium 2 Errata 9: */
 # define FSYS_RETURN                                   \
-       .xdata4 ".data.patch.mckinley_e9", 1f-.;        \
+       .xdata4 ".data..patch.mckinley_e9", 1f-.;       \
 1:{ .mib;                                              \
        nop.m 0;                                        \
        mov r16=ar.pfs;                                 \
@@ -107,11 +107,11 @@ name:
  * If physical stack register size is different from DEF_NUM_STACK_REG,
  * dynamically patch the kernel for correct size.
  */
-       .section ".data.patch.phys_stack_reg", "a"
+       .section ".data..patch.phys_stack_reg", "a"
        .previous
 #define LOAD_PHYS_STACK_REG_SIZE(reg)                  \
 [1:]   adds reg=IA64_NUM_PHYS_STACK_REG*8+8,r0;        \
-       .xdata4 ".data.patch.phys_stack_reg", 1b-.
+       .xdata4 ".data..patch.phys_stack_reg", 1b-.
 
 /*
  * Up until early 2004, use of .align within a function caused bad unwind info.
index e7482bd628ff21ab21d98277d1c2d79f14cfea38..988254a7d34944d5e0cc8f22bb66823af349c86f 100644 (file)
@@ -24,6 +24,6 @@
 # define SMP_CACHE_BYTES       (1 << 3)
 #endif
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #endif /* _ASM_IA64_CACHE_H */
index 1bd4082656940709a715b69b339b86ea3b80db1e..14aa1c58912b6ff70a62d35f77c052fa80ee2930 100644 (file)
@@ -31,7 +31,7 @@ extern void *per_cpu_init(void);
 
 #endif /* SMP */
 
-#define PER_CPU_BASE_SECTION ".data.percpu"
+#define PER_CPU_BASE_SECTION ".data..percpu"
 
 /*
  * Be extremely careful when taking the address of this variable!  Due to virtual
index ab9b03a9adcc4680fd369730e319eeac8fde4728..ceeffc50976462812dec9b9f18105052600862f4 100644 (file)
@@ -21,7 +21,7 @@ GATECFLAGS_gate-syms.o = -r
 $(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE
        $(call if_changed,gate)
 
-# gate-data.o contains the gate DSO image as data in section .data.gate.
+# gate-data.o contains the gate DSO image as data in section .data..gate.
 # We must build gate.so before we can assemble it.
 # Note: kbuild does not track this dependency due to usage of .incbin
 $(obj)/gate-data.o: $(obj)/gate.so
index 258c0a3238fb1984b5cf771261e9d7a185e3e06d..b3ef1c72e132b44e00ade63410380370e25114e2 100644 (file)
@@ -1,3 +1,3 @@
-       .section .data.gate, "aw"
+       .section .data..gate, "aw"
 
        .incbin "arch/ia64/kernel/gate.so"
index cf5e0a105e16521cf20f1fc6aa1957cf5af2e97f..245d3e1ec7e1b00dc97f125f4ef0cc90e45b0aa8 100644 (file)
  * to targets outside the shared object) and to avoid multi-phase kernel builds, we
  * simply create minimalistic "patch lists" in special ELF sections.
  */
-       .section ".data.patch.fsyscall_table", "a"
+       .section ".data..patch.fsyscall_table", "a"
        .previous
 #define LOAD_FSYSCALL_TABLE(reg)                       \
 [1:]   movl reg=0;                                     \
-       .xdata4 ".data.patch.fsyscall_table", 1b-.
+       .xdata4 ".data..patch.fsyscall_table", 1b-.
 
-       .section ".data.patch.brl_fsys_bubble_down", "a"
+       .section ".data..patch.brl_fsys_bubble_down", "a"
        .previous
 #define BRL_COND_FSYS_BUBBLE_DOWN(pr)                  \
 [1:](pr)brl.cond.sptk 0;                               \
        ;;                                              \
-       .xdata4 ".data.patch.brl_fsys_bubble_down", 1b-.
+       .xdata4 ".data..patch.brl_fsys_bubble_down", 1b-.
 
 GLOBAL_ENTRY(__kernel_syscall_via_break)
        .prologue
index 88c64ed47c36bb8d20e9166775bd14cc55f166ed..d32b0855110ae96e358547c9f0c835ae7000f0c2 100644 (file)
@@ -33,21 +33,21 @@ SECTIONS
         */
        . = GATE_ADDR + 0x600;
 
-       .data.patch             : {
+       .data..patch            : {
                __paravirt_start_gate_mckinley_e9_patchlist = .;
-               *(.data.patch.mckinley_e9)
+               *(.data..patch.mckinley_e9)
                __paravirt_end_gate_mckinley_e9_patchlist = .;
 
                __paravirt_start_gate_vtop_patchlist = .;
-               *(.data.patch.vtop)
+               *(.data..patch.vtop)
                __paravirt_end_gate_vtop_patchlist = .;
 
                __paravirt_start_gate_fsyscall_patchlist = .;
-               *(.data.patch.fsyscall_table)
+               *(.data..patch.fsyscall_table)
                __paravirt_end_gate_fsyscall_patchlist = .;
 
                __paravirt_start_gate_brl_fsys_bubble_down_patchlist = .;
-               *(.data.patch.brl_fsys_bubble_down)
+               *(.data..patch.brl_fsys_bubble_down)
                __paravirt_end_gate_brl_fsys_bubble_down_patchlist = .;
        }                                               :readable
 
index e253ab8fcbc8923a789dc12e0afae0dcbf7891b7..f9efe9739d3fe5da25621d278e4c7a2e6a8110e5 100644 (file)
@@ -23,7 +23,7 @@ static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
  * Initial task structure.
  *
  * We need to make sure that this is properly aligned due to the way process stacks are
- * handled. This is done by having a special ".data.init_task" section...
+ * handled. This is done by having a special ".data..init_task" section...
  */
 #define init_thread_info       init_task_mem.s.thread_info
 
index 179fd122e837dadf5bdc153e47aa288592e47ed6..d93e396bf5998813114d0ac1cbbd92551d964551 100644 (file)
@@ -82,7 +82,7 @@
        mov r19=n;;                     /* prepare to save predicates */                \
        br.sptk.many dispatch_to_fault_handler
 
-       .section .text.ivt,"ax"
+       .section .text..ivt,"ax"
 
        .align 32768    // align on 32KB boundary
        .global ia64_ivt
index 292e214a3b84ab323c959e4f7b68283d0275bd2f..d56753a11636b723b402a32df60fc762af3c5e38 100644 (file)
@@ -16,7 +16,7 @@
 #define ACCOUNT_SYS_ENTER
 #endif
 
-.section ".data.patch.rse", "a"
+.section ".data..patch.rse", "a"
 .previous
 
 /*
 (pUStk) extr.u r17=r18,3,6;                    \
 (pUStk)        sub r16=r18,r22;                        \
 [1:](pKStk)    br.cond.sptk.many 1f;           \
-       .xdata4 ".data.patch.rse",1b-.          \
+       .xdata4 ".data..patch.rse",1b-.         \
        ;;                                      \
        cmp.ge p6,p7 = 33,r17;                  \
        ;;                                      \
index 6158560d7f1738993ee4fa00437cd809c8854661..92d880c4d3d1158711759f6b9885fc3c5171f380 100644 (file)
@@ -28,7 +28,7 @@
 #include "entry.h"
 
 #define DATA8(sym, init_value)                 \
-       .pushsection .data.read_mostly ;        \
+       .pushsection .data..read_mostly ;       \
        .align 8 ;                              \
        .global sym ;                           \
        sym: ;                                  \
index 1295ba327f6ff2728f422079aedd6090bc51013b..e07218a2577fc9c797e5237580c510dba23e83e2 100644 (file)
@@ -8,7 +8,7 @@
 
 #define IVT_TEXT                                                       \
                VMLINUX_SYMBOL(__start_ivt_text) = .;                   \
-               *(.text.ivt)                                            \
+               *(.text..ivt)                                           \
                VMLINUX_SYMBOL(__end_ivt_text) = .;
 
 OUTPUT_FORMAT("elf64-ia64-little")
@@ -54,8 +54,8 @@ SECTIONS
   .text2 : AT(ADDR(.text2) - LOAD_OFFSET)
        { *(.text2) }
 #ifdef CONFIG_SMP
-  .text.lock : AT(ADDR(.text.lock) - LOAD_OFFSET)
-       { *(.text.lock) }
+  .text..lock : AT(ADDR(.text..lock) - LOAD_OFFSET)
+       { *(.text..lock) }
 #endif
   _etext = .;
 
@@ -75,10 +75,10 @@ SECTIONS
          __stop___mca_table = .;
        }
 
-  .data.patch.phys_stack_reg : AT(ADDR(.data.patch.phys_stack_reg) - LOAD_OFFSET)
+  .data..patch.phys_stack_reg : AT(ADDR(.data..patch.phys_stack_reg) - LOAD_OFFSET)
        {
          __start___phys_stack_reg_patchlist = .;
-         *(.data.patch.phys_stack_reg)
+         *(.data..patch.phys_stack_reg)
          __end___phys_stack_reg_patchlist = .;
        }
 
@@ -110,24 +110,24 @@ SECTIONS
   INIT_TEXT_SECTION(PAGE_SIZE)
   INIT_DATA_SECTION(16)
 
-  .data.patch.vtop : AT(ADDR(.data.patch.vtop) - LOAD_OFFSET)
+  .data..patch.vtop : AT(ADDR(.data..patch.vtop) - LOAD_OFFSET)
        {
          __start___vtop_patchlist = .;
-         *(.data.patch.vtop)
+         *(.data..patch.vtop)
          __end___vtop_patchlist = .;
        }
 
-  .data.patch.rse : AT(ADDR(.data.patch.rse) - LOAD_OFFSET)
+  .data..patch.rse : AT(ADDR(.data..patch.rse) - LOAD_OFFSET)
        {
          __start___rse_patchlist = .;
-         *(.data.patch.rse)
+         *(.data..patch.rse)
          __end___rse_patchlist = .;
        }
 
-  .data.patch.mckinley_e9 : AT(ADDR(.data.patch.mckinley_e9) - LOAD_OFFSET)
+  .data..patch.mckinley_e9 : AT(ADDR(.data..patch.mckinley_e9) - LOAD_OFFSET)
        {
          __start___mckinley_e9_bundles = .;
-         *(.data.patch.mckinley_e9)
+         *(.data..patch.mckinley_e9)
          __end___mckinley_e9_bundles = .;
        }
 
@@ -175,17 +175,17 @@ SECTIONS
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
-  .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET)
+  .data..page_aligned : AT(ADDR(.data..page_aligned) - LOAD_OFFSET)
         {
        PAGE_ALIGNED_DATA(PAGE_SIZE)
          . = ALIGN(PAGE_SIZE);
          __start_gate_section = .;
-         *(.data.gate)
+         *(.data..gate)
          __stop_gate_section = .;
 #ifdef CONFIG_XEN
          . = ALIGN(PAGE_SIZE);
          __xen_start_gate_section = .;
-         *(.data.gate.xen)
+         *(.data..gate.xen)
          __xen_stop_gate_section = .;
 #endif
        }
index d5f4e9161201f648dbaf90ec96c300ec63d6536b..21b701374f72335905ee9bfde866975e60800229 100644 (file)
@@ -144,6 +144,7 @@ int kvm_arch_hardware_enable(void *garbage)
                                VP_INIT_ENV : VP_INIT_ENV_INITALIZE,
                        __pa(kvm_vm_buffer), KVM_VM_BUFFER_BASE, &tmp_base);
        if (status != 0) {
+               spin_unlock(&vp_lock);
                printk(KERN_WARNING"kvm: Failed to Enable VT Support!!!!\n");
                return -EINVAL;
        }
index 40920c630649c3affa7556c355fea302b614f2a3..24018484c6e93391060e0157540d804867bb6f58 100644 (file)
@@ -104,7 +104,7 @@ GLOBAL_ENTRY(kvm_vmm_panic)
        br.call.sptk.many b6=vmm_panic_handler;
 END(kvm_vmm_panic)
 
-    .section .text.ivt,"ax"
+    .section .text..ivt,"ax"
 
     .align 32768    // align on 32KB boundary
     .global kvm_ia64_ivt
index 5dfd916e9ea610db1a047e0462d6398082bde63e..7b3cdc6c6d9147d3edd422ab31b97adf90e46f6c 100644 (file)
@@ -121,7 +121,7 @@ static inline void down_spin(struct spinaphore *ss)
        ia64_invala();
 
        for (;;) {
-               asm volatile ("ld4.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
+               asm volatile ("ld8.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
                if (time_before(t, serve))
                        return;
                cpu_relax();
index c27849889e193f4d3a8479b5e5db470cccc2493d..2bfd941ff7c7cdb5a96622875e5d7507125623b3 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
 #
 # Usage: unwcheck.py FILE
 #
index 7d4830afc91dc3351e6e5599f8c6173991178b1b..6f95b6b32a4efdb1af974875475b607a3deb91db 100644 (file)
@@ -1,3 +1,3 @@
-       .section .data.gate.xen, "aw"
+       .section .data..gate.xen, "aw"
 
        .incbin "arch/ia64/xen/gate.so"
index aff8346ea193536f035fe81f2c5490707256b537..b820ed02ab9f67b0452136326da826e0cc977261 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/init.h>
 #include <xen/interface/elfnote.h>
 
-       .section .data.read_mostly
+       .section .data..read_mostly
        .align 8
        .global xen_domain_type
 xen_domain_type:
index 28ee389e5f5a3e43d39f8d5f1cdccf45923785d3..b8ec002aef8e321349f17b9255b70762b4b029ce 100644 (file)
@@ -188,7 +188,6 @@ good_area:
        if ((error_code & ACE_INSTRUCTION) && !(vma->vm_flags & VM_EXEC))
          goto bad_area;
 
-survive:
        /*
         * If for any reason at all we couldn't handle the fault,
         * make sure we exit gracefully rather than endlessly redo
@@ -271,15 +270,10 @@ no_context:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (is_global_init(tsk)) {
-               yield();
-               down_read(&mm->mmap_sem);
-               goto survive;
-       }
-       printk("VM: killing process %s\n", tsk->comm);
-       if (error_code & ACE_USERMODE)
-               do_group_exit(SIGKILL);
-       goto no_context;
+       if (!(error_code & ACE_USERMODE))
+               goto no_context;
+       pagefault_out_of_memory();
+       return;
 
 do_sigbus:
        up_read(&mm->mmap_sem);
index 9f1784f586b95db2d35227189762f8ed22a63517..a91b2713451da0e5290a3889e1bcebbb530c0e4b 100644 (file)
@@ -57,7 +57,7 @@ SECTIONS {
        .romvec : {
                __rom_start = . ;
                _romvec = .;
-               *(.data.initvect)
+               *(.data..initvect)
        } > romvec
 #endif
 
@@ -68,7 +68,7 @@ SECTIONS {
                TEXT_TEXT
                SCHED_TEXT
                LOCK_TEXT
-               *(.text.lock)
+               *(.text..lock)
 
                . = ALIGN(16);          /* Exception table              */
                __start___ex_table = .;
index 2ef06242398bf8bbad01b207f6436ff38cfe6ddb..8eb94fb6b971a3c35867f558096af9a6f7cd6b0e 100644 (file)
@@ -280,7 +280,7 @@ _dprbase:
      * and then overwritten as needed.
      */
  
-.section ".data.initvect","awx"
+.section ".data..initvect","awx"
     .long   RAMEND     /* Reset: Initial Stack Pointer                 - 0.  */
     .long   _start      /* Reset: Initial Program Counter               - 1.  */
     .long   buserr      /* Bus Error                                    - 2.  */
index 62ecf4144b3ba3ad2df0ebecbb13adca1feff5b6..97510e55b802a587ad547c9f36005540ae2c8fc5 100644 (file)
@@ -291,7 +291,7 @@ _dprbase:
      * and then overwritten as needed.
      */
  
-.section ".data.initvect","awx"
+.section ".data..initvect","awx"
     .long   RAMEND     /* Reset: Initial Stack Pointer                 - 0.  */
     .long   _start      /* Reset: Initial Program Counter               - 1.  */
     .long   buserr      /* Bus Error                                    - 2.  */
index de493f86d28f7884b2adb7a625c0848a38aa6b74..464ff32bee3d29139cebead6a21be92207016a36 100644 (file)
@@ -34,6 +34,8 @@
 /* MS be sure that SLAB allocates aligned objects */
 #define ARCH_KMALLOC_MINALIGN  L1_CACHE_BYTES
 
+#define ARCH_SLAB_MINALIGN     L1_CACHE_BYTES
+
 #define PAGE_UP(addr)  (((addr)+((PAGE_SIZE)-1))&(~((PAGE_SIZE)-1)))
 #define PAGE_DOWN(addr)        ((addr)&(~((PAGE_SIZE)-1)))
 
index 9dcd90b5df55bdf08cd869fba62f56219797c555..79c74659f204b7da1aed7172f255f4556cbc77fb 100644 (file)
@@ -90,7 +90,6 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
        /* FIXME this part of code is untested */
        for_each_sg(sgl, sg, nents, i) {
                sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev);
-               sg->dma_length = sg->length;
                __dma_sync_page(page_to_phys(sg_page(sg)), sg->offset,
                                                        sg->length, direction);
        }
index 9cb782b8e036f763b09d61054652897da5c9141b..23be25fec4d67bf7e48d612b50e1da9f766371ae 100644 (file)
@@ -1277,6 +1277,7 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
                printk(KERN_WARNING "PCI: Cannot allocate resource region "
                       "%d of PCI bridge %d, will remap\n", i, bus->number);
 clear_resource:
+               res->start = res->end = 0;
                res->flags = 0;
        }
 
index efb95f2609c2a1cb1a52e8b21a3ee2eae3f50566..e0ecda92c40a86603293911e657b3a850ed3ade8 100644 (file)
@@ -1,7 +1,7 @@
 #include <asm/lasat/head.h>
 
        .text
-       .section .text.start, "ax"
+       .section .text..start, "ax"
        .set noreorder
        .set mips3
 
index 988f8ad189cb19d29c47a489f07e10190b934985..0864c963e188d6872385606ecaeb917d23319ccb 100644 (file)
@@ -4,7 +4,7 @@ SECTIONS
 {
   .text :
   {
-    *(.text.start)
+    *(.text..start)
   }
 
   /* Data in ROM */
index 53bb17d0f0687764ab1d8a4e05d6cdfc81c03e25..81f153fa51b4a6ecb07111f1d20383fbf0b6eaf2 100644 (file)
@@ -338,11 +338,10 @@ no_context:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       monitor_signal(regs);
-       printk(KERN_ALERT "VM: killing process %s\n", tsk->comm);
-       if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
-               do_exit(SIGKILL);
-       goto no_context;
+       if ((fault_code & MMUFCR_xFC_ACCESS) != MMUFCR_xFC_ACCESS_USR)
+               goto no_context;
+       pagefault_out_of_memory();
+       return;
 
 do_sigbus:
        up_read(&mm->mmap_sem);
index d6119b879a9812f9f1e50749b06d764c38ebfb5c..45b40ac6c4647b3bb0751a1352e21e2e0a66ae3e 100644 (file)
@@ -117,6 +117,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
                                         * Invalidate the resource to prevent
                                         * child resource allocations in this
                                         * range. */
+                                       r->start = r->end = 0;
                                        r->flags = 0;
                                }
                        }
index 32c2cca74345995d9cdbc80fc46c59081f734871..45effe6978faaa766203c085e6a458faea7800be 100644 (file)
@@ -28,7 +28,7 @@
 
 #define SMP_CACHE_BYTES L1_CACHE_BYTES
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 void parisc_cache_init(void);  /* initializes cache-flushing */
 void disable_sr_hashing_asm(int); /* low level support for above */
index 4653c77bf9d13398c6dd6777786a20c3a821c2dd..2ab4af58ecb9ca20cf13751868c917fe09b36a7b 100644 (file)
@@ -174,7 +174,7 @@ static inline void set_eiem(unsigned long val)
 })
 
 #ifdef CONFIG_SMP
-# define __lock_aligned __attribute__((__section__(".data.lock_aligned")))
+# define __lock_aligned __attribute__((__section__(".data..lock_aligned")))
 #endif
 
 #define arch_align_stack(x) (x)
index 0e3d9f9b9e33e97680190e3752cea063fce9c251..4dbdf0ed6fa0f08b37bd4ac77e205c9d7e6af2ad 100644 (file)
@@ -345,7 +345,7 @@ smp_slave_stext:
 ENDPROC(stext)
 
 #ifndef CONFIG_64BIT
-       .section .data.read_mostly
+       .section .data..read_mostly
 
        .align  4
        .export $global$,data
index d020eae6525c4a200e9bcab86b6b8beb3e2ef5b3..4a91e433416f17b4f0df48a7e66035cde928303f 100644 (file)
@@ -53,11 +53,11 @@ union thread_union init_thread_union __init_task_data
  * guarantee that global objects will be laid out in memory in the same order 
  * as the order of declaration, so put these in different sections and use
  * the linker script to order them. */
-pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data.vm0.pmd"), aligned(PAGE_SIZE)));
+pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data..vm0.pmd"), aligned(PAGE_SIZE)));
 #endif
 
-pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data.vm0.pgd"), aligned(PAGE_SIZE)));
-pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data.vm0.pte"), aligned(PAGE_SIZE)));
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data..vm0.pgd"), aligned(PAGE_SIZE)));
+pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data..vm0.pte"), aligned(PAGE_SIZE)));
 
 /*
  * Initial task structure.
index 9dab4a4e09f7af86d5dbe6a5a8e129393d619a42..d64a6bbec2aa0585b380e485c600db818219b51e 100644 (file)
@@ -94,8 +94,8 @@ SECTIONS
 
        /* PA-RISC locks requires 16-byte alignment */
        . = ALIGN(16);
-       .data.lock_aligned : {
-               *(.data.lock_aligned)
+       .data..lock_aligned : {
+               *(.data..lock_aligned)
        }
 
        /* End of data section */
@@ -105,10 +105,10 @@ SECTIONS
        __bss_start = .;
        /* page table entries need to be PAGE_SIZE aligned */
        . = ALIGN(PAGE_SIZE);
-       .data.vmpages : {
-               *(.data.vm0.pmd)
-               *(.data.vm0.pgd)
-               *(.data.vm0.pte)
+       .data..vmpages : {
+               *(.data..vm0.pmd)
+               *(.data..vm0.pgd)
+               *(.data..vm0.pte)
        }
        .bss : {
                *(.bss)
index 66a315e06dce88691322901a7ab7c6d38c702f4b..328774bd41ee171706de902d5640721bfc49b0d2 100644 (file)
@@ -351,7 +351,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
 
 config KEXEC
        bool "kexec system call (EXPERIMENTAL)"
-       depends on PPC_BOOK3S && EXPERIMENTAL
+       depends on (PPC_BOOK3S || (FSL_BOOKE && !SMP)) && EXPERIMENTAL
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
index 53696da4518f9569aabf9a4b668cb725f1a5c4a1..2d38a50e66ba45c5ca0779bbec98efb39cb7fdcf 100644 (file)
@@ -135,13 +135,6 @@ config DEBUGGER
        depends on KGDB || XMON
        default y
 
-config IRQSTACKS
-       bool "Use separate kernel stacks when processing interrupts"
-       help
-         If you say Y here the kernel will use separate kernel stacks
-         for handling hard and soft interrupts.  This can help avoid
-         overflowing the process kernel stacks.
-
 config VIRQ_DEBUG
        bool "Expose hardware/virtual IRQ mapping via debugfs"
        depends on DEBUG_FS
index 1a54a3b3a3fa8da5397842d5cbbd2e370dc6d40b..42dcd3f4ad7b5d45241e7057804a100cb6df9375 100644 (file)
@@ -112,6 +112,11 @@ KBUILD_CFLAGS += $(call cc-option,-mspe=no)
 # kernel considerably.
 KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
 
+# FIXME: the module load should be taught about the additional relocs
+# generated by this.
+# revert to pre-gcc-4.4 behaviour of .eh_frame
+KBUILD_CFLAGS  += $(call cc-option,-fno-dwarf2-cfi-asm)
+
 # Never use string load/store instructions as they are
 # often slow when they are implemented at all
 KBUILD_CFLAGS          += -mno-string
index 27db8938827aee7381cc065fade0d12fb0c2d528..9d3bd4c45a2406992005018d70f1db1e1f56b591 100644 (file)
@@ -519,7 +519,7 @@ void ibm440ep_fixup_clocks(unsigned int sys_clk,
 {
        unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 0);
 
-       /* serial clocks beed fixup based on int/ext */
+       /* serial clocks need fixup based on int/ext */
        eplike_fixup_uart_clk(0, "/plb/opb/serial@ef600300", ser_clk, plb_clk);
        eplike_fixup_uart_clk(1, "/plb/opb/serial@ef600400", ser_clk, plb_clk);
        eplike_fixup_uart_clk(2, "/plb/opb/serial@ef600500", ser_clk, plb_clk);
@@ -532,7 +532,7 @@ void ibm440gx_fixup_clocks(unsigned int sys_clk,
 {
        unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
 
-       /* serial clocks beed fixup based on int/ext */
+       /* serial clocks need fixup based on int/ext */
        eplike_fixup_uart_clk(0, "/plb/opb/serial@40000200", ser_clk, plb_clk);
        eplike_fixup_uart_clk(1, "/plb/opb/serial@40000300", ser_clk, plb_clk);
 }
@@ -543,10 +543,10 @@ void ibm440spe_fixup_clocks(unsigned int sys_clk,
 {
        unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
 
-       /* serial clocks beed fixup based on int/ext */
-       eplike_fixup_uart_clk(0, "/plb/opb/serial@10000200", ser_clk, plb_clk);
-       eplike_fixup_uart_clk(1, "/plb/opb/serial@10000300", ser_clk, plb_clk);
-       eplike_fixup_uart_clk(2, "/plb/opb/serial@10000600", ser_clk, plb_clk);
+       /* serial clocks need fixup based on int/ext */
+       eplike_fixup_uart_clk(0, "/plb/opb/serial@f0000200", ser_clk, plb_clk);
+       eplike_fixup_uart_clk(1, "/plb/opb/serial@f0000300", ser_clk, plb_clk);
+       eplike_fixup_uart_clk(2, "/plb/opb/serial@f0000600", ser_clk, plb_clk);
 }
 
 void ibm405gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
index ad0df7d0a6435b85589b18b3c710c46ead736fd8..fae8192c8fcce0a7069b1d7dff785f5fdda67273 100644 (file)
@@ -141,7 +141,7 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S FORCE
 $(obj)/wrapper.a: $(obj-wlib) FORCE
        $(call if_changed,bootar)
 
-hostprogs-y    := addnote addRamDisk hack-coff mktree
+hostprogs-y    := addnote hack-coff mktree
 
 targets                += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
 extra-y                := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
diff --git a/arch/powerpc/boot/addRamDisk.c b/arch/powerpc/boot/addRamDisk.c
deleted file mode 100644 (file)
index 893f446..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <elf.h>
-
-#define ElfHeaderSize  (64 * 1024)
-#define ElfPages  (ElfHeaderSize / 4096)
-#define KERNELBASE (0xc000000000000000)
-#define _ALIGN_UP(addr,size)   (((addr)+((size)-1))&(~((size)-1)))
-
-struct addr_range {
-       unsigned long long addr;
-       unsigned long memsize;
-       unsigned long offset;
-};
-
-static int check_elf64(void *p, int size, struct addr_range *r)
-{
-       Elf64_Ehdr *elf64 = p;
-       Elf64_Phdr *elf64ph;
-
-       if (elf64->e_ident[EI_MAG0] != ELFMAG0 ||
-           elf64->e_ident[EI_MAG1] != ELFMAG1 ||
-           elf64->e_ident[EI_MAG2] != ELFMAG2 ||
-           elf64->e_ident[EI_MAG3] != ELFMAG3 ||
-           elf64->e_ident[EI_CLASS] != ELFCLASS64 ||
-           elf64->e_ident[EI_DATA] != ELFDATA2MSB ||
-           elf64->e_type != ET_EXEC || elf64->e_machine != EM_PPC64)
-               return 0;
-
-       if ((elf64->e_phoff + sizeof(Elf64_Phdr)) > size)
-               return 0;
-
-       elf64ph = (Elf64_Phdr *) ((unsigned long)elf64 +
-                                 (unsigned long)elf64->e_phoff);
-
-       r->memsize = (unsigned long)elf64ph->p_memsz;
-       r->offset = (unsigned long)elf64ph->p_offset;
-       r->addr = (unsigned long long)elf64ph->p_vaddr;
-
-#ifdef DEBUG
-       printf("PPC64 ELF file, ph:\n");
-       printf("p_type   0x%08x\n", elf64ph->p_type);
-       printf("p_flags  0x%08x\n", elf64ph->p_flags);
-       printf("p_offset 0x%016llx\n", elf64ph->p_offset);
-       printf("p_vaddr  0x%016llx\n", elf64ph->p_vaddr);
-       printf("p_paddr  0x%016llx\n", elf64ph->p_paddr);
-       printf("p_filesz 0x%016llx\n", elf64ph->p_filesz);
-       printf("p_memsz  0x%016llx\n", elf64ph->p_memsz);
-       printf("p_align  0x%016llx\n", elf64ph->p_align);
-       printf("... skipping 0x%08lx bytes of ELF header\n",
-              (unsigned long)elf64ph->p_offset);
-#endif
-
-       return 64;
-}
-static void get4k(FILE *file, char *buf )
-{
-       unsigned j;
-       unsigned num = fread(buf, 1, 4096, file);
-       for ( j=num; j<4096; ++j )
-               buf[j] = 0;
-}
-
-static void put4k(FILE *file, char *buf )
-{
-       fwrite(buf, 1, 4096, file);
-}
-
-static void death(const char *msg, FILE *fdesc, const char *fname)
-{
-       fprintf(stderr, msg);
-       fclose(fdesc);
-       unlink(fname);
-       exit(1);
-}
-
-int main(int argc, char **argv)
-{
-       char inbuf[4096];
-       struct addr_range vmlinux;
-       FILE *ramDisk;
-       FILE *inputVmlinux;
-       FILE *outputVmlinux;
-
-       char *rd_name, *lx_name, *out_name;
-
-       size_t i;
-       unsigned long ramFileLen;
-       unsigned long ramLen;
-       unsigned long roundR;
-       unsigned long offset_end;
-
-       unsigned long kernelLen;
-       unsigned long actualKernelLen;
-       unsigned long round;
-       unsigned long roundedKernelLen;
-       unsigned long ramStartOffs;
-       unsigned long ramPages;
-       unsigned long roundedKernelPages;
-       unsigned long hvReleaseData;
-       u_int32_t eyeCatcher = 0xc8a5d9c4;
-       unsigned long naca;
-       unsigned long xRamDisk;
-       unsigned long xRamDiskSize;
-       long padPages;
-  
-  
-       if (argc < 2) {
-               fprintf(stderr, "Name of RAM disk file missing.\n");
-               exit(1);
-       }
-       rd_name = argv[1];
-
-       if (argc < 3) {
-               fprintf(stderr, "Name of vmlinux file missing.\n");
-               exit(1);
-       }
-       lx_name = argv[2];
-
-       if (argc < 4) {
-               fprintf(stderr, "Name of vmlinux output file missing.\n");
-               exit(1);
-       }
-       out_name = argv[3];
-
-
-       ramDisk = fopen(rd_name, "r");
-       if ( ! ramDisk ) {
-               fprintf(stderr, "RAM disk file \"%s\" failed to open.\n", rd_name);
-               exit(1);
-       }
-
-       inputVmlinux = fopen(lx_name, "r");
-       if ( ! inputVmlinux ) {
-               fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", lx_name);
-               exit(1);
-       }
-  
-       outputVmlinux = fopen(out_name, "w+");
-       if ( ! outputVmlinux ) {
-               fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", out_name);
-               exit(1);
-       }
-
-       i = fread(inbuf, 1, sizeof(inbuf), inputVmlinux);
-       if (i != sizeof(inbuf)) {
-               fprintf(stderr, "can not read vmlinux file %s: %u\n", lx_name, i);
-               exit(1);
-       }
-
-       i = check_elf64(inbuf, sizeof(inbuf), &vmlinux);
-       if (i == 0) {
-               fprintf(stderr, "You must have a linux kernel specified as argv[2]\n");
-               exit(1);
-       }
-
-       /* Input Vmlinux file */
-       fseek(inputVmlinux, 0, SEEK_END);
-       kernelLen = ftell(inputVmlinux);
-       fseek(inputVmlinux, 0, SEEK_SET);
-       printf("kernel file size = %lu\n", kernelLen);
-
-       actualKernelLen = kernelLen - ElfHeaderSize;
-
-       printf("actual kernel length (minus ELF header) = %lu\n", actualKernelLen);
-
-       round = actualKernelLen % 4096;
-       roundedKernelLen = actualKernelLen;
-       if ( round )
-               roundedKernelLen += (4096 - round);
-       printf("Vmlinux length rounded up to a 4k multiple = %ld/0x%lx \n", roundedKernelLen, roundedKernelLen);
-       roundedKernelPages = roundedKernelLen / 4096;
-       printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages);
-
-       offset_end = _ALIGN_UP(vmlinux.memsize, 4096);
-       /* calc how many pages we need to insert between the vmlinux and the start of the ram disk */
-       padPages = offset_end/4096 - roundedKernelPages;
-
-       /* Check and see if the vmlinux is already larger than _end in System.map */
-       if (padPages < 0) {
-               /* vmlinux is larger than _end - adjust the offset to the start of the embedded ram disk */ 
-               offset_end = roundedKernelLen;
-               printf("vmlinux is larger than _end indicates it needs to be - offset_end = %lx \n", offset_end);
-               padPages = 0;
-               printf("will insert %lx pages between the vmlinux and the start of the ram disk \n", padPages);
-       }
-       else {
-               /* _end is larger than vmlinux - use the offset to _end that we calculated from the system map */
-               printf("vmlinux is smaller than _end indicates is needed - offset_end = %lx \n", offset_end);
-               printf("will insert %lx pages between the vmlinux and the start of the ram disk \n", padPages);
-       }
-
-
-
-       /* Input Ram Disk file */
-       // Set the offset that the ram disk will be started at.
-       ramStartOffs = offset_end;  /* determined from the input vmlinux file and the system map */
-       printf("Ram Disk will start at offset = 0x%lx \n", ramStartOffs);
-  
-       fseek(ramDisk, 0, SEEK_END);
-       ramFileLen = ftell(ramDisk);
-       fseek(ramDisk, 0, SEEK_SET);
-       printf("%s file size = %ld/0x%lx \n", rd_name, ramFileLen, ramFileLen);
-
-       ramLen = ramFileLen;
-
-       roundR = 4096 - (ramLen % 4096);
-       if ( roundR ) {
-               printf("Rounding RAM disk file up to a multiple of 4096, adding %ld/0x%lx \n", roundR, roundR);
-               ramLen += roundR;
-       }
-
-       printf("Rounded RAM disk size is %ld/0x%lx \n", ramLen, ramLen);
-       ramPages = ramLen / 4096;
-       printf("RAM disk pages to copy = %ld/0x%lx\n", ramPages, ramPages);
-
-
-
-  // Copy 64K ELF header
-       for (i=0; i<(ElfPages); ++i) {
-               get4k( inputVmlinux, inbuf );
-               put4k( outputVmlinux, inbuf );
-       }
-
-       /* Copy the vmlinux (as full pages). */
-       fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
-       for ( i=0; i<roundedKernelPages; ++i ) {
-               get4k( inputVmlinux, inbuf );
-               put4k( outputVmlinux, inbuf );
-       }
-  
-       /* Insert pad pages (if appropriate) that are needed between */
-       /* | the end of the vmlinux and the ram disk. */
-       for (i=0; i<padPages; ++i) {
-               memset(inbuf, 0, 4096);
-               put4k(outputVmlinux, inbuf);
-       }
-
-       /* Copy the ram disk (as full pages). */
-       for ( i=0; i<ramPages; ++i ) {
-               get4k( ramDisk, inbuf );
-               put4k( outputVmlinux, inbuf );
-       }
-
-       /* Close the input files */
-       fclose(ramDisk);
-       fclose(inputVmlinux);
-       /* And flush the written output file */
-       fflush(outputVmlinux);
-
-
-
-       /* Fixup the new vmlinux to contain the ram disk starting offset (xRamDisk) and the ram disk size (xRamDiskSize) */
-       /* fseek to the hvReleaseData pointer */
-       fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET);
-       if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) {
-               death("Could not read hvReleaseData pointer\n", outputVmlinux, out_name);
-       }
-       hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */
-       printf("hvReleaseData is at %08lx\n", hvReleaseData);
-
-       /* fseek to the hvReleaseData */
-       fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET);
-       if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) {
-               death("Could not read hvReleaseData\n", outputVmlinux, out_name);
-       }
-       /* Check hvReleaseData sanity */
-       if (memcmp(inbuf, &eyeCatcher, 4) != 0) {
-               death("hvReleaseData is invalid\n", outputVmlinux, out_name);
-       }
-       /* Get the naca pointer */
-       naca = ntohl(*((u_int32_t*) &inbuf[0x0C])) - KERNELBASE;
-       printf("Naca is at offset 0x%lx \n", naca);
-
-       /* fseek to the naca */
-       fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
-       if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) {
-               death("Could not read naca\n", outputVmlinux, out_name);
-       }
-       xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c]));
-       xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14]));
-       /* Make sure a RAM disk isn't already present */
-       if ((xRamDisk != 0) || (xRamDiskSize != 0)) {
-               death("RAM disk is already attached to this kernel\n", outputVmlinux, out_name);
-       }
-       /* Fill in the values */
-       *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs);
-       *((u_int32_t *) &inbuf[0x14]) = htonl(ramPages);
-
-       /* Write out the new naca */
-       fflush(outputVmlinux);
-       fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
-       if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) {
-               death("Could not write naca\n", outputVmlinux, out_name);
-       }
-       printf("Ram Disk of 0x%lx pages is attached to the kernel at offset 0x%08lx\n",
-              ramPages, ramStartOffs);
-
-       /* Done */
-       fclose(outputVmlinux);
-       /* Set permission to executable */
-       chmod(out_name, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
-
-       return 0;
-}
-
diff --git a/arch/powerpc/boot/dts/icon.dts b/arch/powerpc/boot/dts/icon.dts
new file mode 100644 (file)
index 0000000..abcd0ca
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * Device Tree Source for Mosaix Technologies, Inc. ICON board
+ *
+ * Copyright 2010 DENX Software Engineering, Stefan Roese <sr@denx.de>
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/ {
+       #address-cells = <2>;
+       #size-cells = <2>;
+       model = "mosaixtech,icon";
+       compatible = "mosaixtech,icon";
+       dcr-parent = <&{/cpus/cpu@0}>;
+
+       aliases {
+               ethernet0 = &EMAC0;
+               serial0 = &UART0;
+               serial1 = &UART1;
+               serial2 = &UART2;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       model = "PowerPC,440SPe";
+                       reg = <0x00000000>;
+                       clock-frequency = <0>; /* Filled in by U-Boot */
+                       timebase-frequency = <0>; /* Filled in by U-Boot */
+                       i-cache-line-size = <32>;
+                       d-cache-line-size = <32>;
+                       i-cache-size = <32768>;
+                       d-cache-size = <32768>;
+                       dcr-controller;
+                       dcr-access-method = "native";
+                       reset-type = <2>;       /* Use chip-reset */
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x00000000 0x0 0x00000000>; /* Filled in by U-Boot */
+       };
+
+       UIC0: interrupt-controller0 {
+               compatible = "ibm,uic-440spe","ibm,uic";
+               interrupt-controller;
+               cell-index = <0>;
+               dcr-reg = <0x0c0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+       };
+
+       UIC1: interrupt-controller1 {
+               compatible = "ibm,uic-440spe","ibm,uic";
+               interrupt-controller;
+               cell-index = <1>;
+               dcr-reg = <0x0d0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+               interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */
+               interrupt-parent = <&UIC0>;
+       };
+
+       UIC2: interrupt-controller2 {
+               compatible = "ibm,uic-440spe","ibm,uic";
+               interrupt-controller;
+               cell-index = <2>;
+               dcr-reg = <0x0e0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+               interrupts = <0xa 0x4 0xb 0x4>; /* cascade */
+               interrupt-parent = <&UIC0>;
+       };
+
+       UIC3: interrupt-controller3 {
+               compatible = "ibm,uic-440spe","ibm,uic";
+               interrupt-controller;
+               cell-index = <3>;
+               dcr-reg = <0x0f0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+               interrupts = <0x10 0x4 0x11 0x4>; /* cascade */
+               interrupt-parent = <&UIC0>;
+       };
+
+       SDR0: sdr {
+               compatible = "ibm,sdr-440spe";
+               dcr-reg = <0x00e 0x002>;
+       };
+
+       CPR0: cpr {
+               compatible = "ibm,cpr-440spe";
+               dcr-reg = <0x00c 0x002>;
+       };
+
+       MQ0: mq {
+               compatible = "ibm,mq-440spe";
+               dcr-reg = <0x040 0x020>;
+       };
+
+       plb {
+               compatible = "ibm,plb-440spe", "ibm,plb-440gp", "ibm,plb4";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               /*        addr-child     addr-parent    size */
+               ranges = <0x4 0x00100000 0x4 0x00100000 0x00001000
+                         0x4 0x00200000 0x4 0x00200000 0x00000400
+                         0x4 0xe0000000 0x4 0xe0000000 0x20000000
+                         0xc 0x00000000 0xc 0x00000000 0x20000000
+                         0xd 0x00000000 0xd 0x00000000 0x80000000
+                         0xd 0x80000000 0xd 0x80000000 0x80000000
+                         0xe 0x00000000 0xe 0x00000000 0x80000000
+                         0xe 0x80000000 0xe 0x80000000 0x80000000
+                         0xf 0x00000000 0xf 0x00000000 0x80000000
+                         0xf 0x80000000 0xf 0x80000000 0x80000000>;
+               clock-frequency = <0>; /* Filled in by U-Boot */
+
+               SDRAM0: sdram {
+                       compatible = "ibm,sdram-440spe", "ibm,sdram-405gp";
+                       dcr-reg = <0x010 0x002>;
+               };
+
+               MAL0: mcmal {
+                       compatible = "ibm,mcmal-440spe", "ibm,mcmal2";
+                       dcr-reg = <0x180 0x062>;
+                       num-tx-chans = <2>;
+                       num-rx-chans = <1>;
+                       interrupt-parent = <&MAL0>;
+                       interrupts = <0x0 0x1 0x2 0x3 0x4>;
+                       #interrupt-cells = <1>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = </*TXEOB*/ 0x0 &UIC1 0x6 0x4
+                                        /*RXEOB*/ 0x1 &UIC1 0x7 0x4
+                                        /*SERR*/  0x2 &UIC1 0x1 0x4
+                                        /*TXDE*/  0x3 &UIC1 0x2 0x4
+                                        /*RXDE*/  0x4 &UIC1 0x3 0x4>;
+               };
+
+               POB0: opb {
+                       compatible = "ibm,opb-440spe", "ibm,opb-440gp", "ibm,opb";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0xe0000000 0x00000004 0xe0000000 0x20000000>;
+                       clock-frequency = <0>; /* Filled in by U-Boot */
+
+                       EBC0: ebc {
+                               compatible = "ibm,ebc-440spe", "ibm,ebc-440gp", "ibm,ebc";
+                               dcr-reg = <0x012 0x002>;
+                               #address-cells = <2>;
+                               #size-cells = <1>;
+                               clock-frequency = <0>; /* Filled in by U-Boot */
+                               /* ranges property is supplied by U-Boot */
+                               interrupts = <0x5 0x1>;
+                               interrupt-parent = <&UIC1>;
+
+                               nor_flash@0,0 {
+                                       compatible = "cfi-flash";
+                                       bank-width = <2>;
+                                       reg = <0x00000000 0x00000000 0x01000000>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                                       partition@0 {
+                                               label = "kernel";
+                                               reg = <0x00000000 0x001e0000>;
+                                       };
+                                       partition@1e0000 {
+                                               label = "dtb";
+                                               reg = <0x001e0000 0x00020000>;
+                                       };
+                                       partition@200000 {
+                                               label = "root";
+                                               reg = <0x00200000 0x00200000>;
+                                       };
+                                       partition@400000 {
+                                               label = "user";
+                                               reg = <0x00400000 0x00b60000>;
+                                       };
+                                       partition@f60000 {
+                                               label = "env";
+                                               reg = <0x00f60000 0x00040000>;
+                                       };
+                                       partition@fa0000 {
+                                               label = "u-boot";
+                                               reg = <0x00fa0000 0x00060000>;
+                                       };
+                               };
+
+                               SysACE_CompactFlash: sysace@1,0 {
+                                       compatible = "xlnx,sysace";
+                                       interrupt-parent = <&UIC2>;
+                                       interrupts = <24 0x4>;
+                                       reg = <0x00000001 0x00000000 0x10000>;
+                               };
+                       };
+
+                       UART0: serial@f0000200 {
+                               device_type = "serial";
+                               compatible = "ns16550";
+                               reg = <0xf0000200 0x00000008>;
+                               virtual-reg = <0xa0000200>;
+                               clock-frequency = <0>; /* Filled in by U-Boot */
+                               current-speed = <115200>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <0x0 0x4>;
+                       };
+
+                       UART1: serial@f0000300 {
+                               device_type = "serial";
+                               compatible = "ns16550";
+                               reg = <0xf0000300 0x00000008>;
+                               virtual-reg = <0xa0000300>;
+                               clock-frequency = <0>;
+                               current-speed = <0>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <0x1 0x4>;
+                       };
+
+
+                       UART2: serial@f0000600 {
+                               device_type = "serial";
+                               compatible = "ns16550";
+                               reg = <0xf0000600 0x00000008>;
+                               virtual-reg = <0xa0000600>;
+                               clock-frequency = <0>;
+                               current-speed = <0>;
+                               interrupt-parent = <&UIC1>;
+                               interrupts = <0x5 0x4>;
+                       };
+
+                       IIC0: i2c@f0000400 {
+                               compatible = "ibm,iic-440spe", "ibm,iic-440gp", "ibm,iic";
+                               reg = <0xf0000400 0x00000014>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <0x2 0x4>;
+                       };
+
+                       IIC1: i2c@f0000500 {
+                               compatible = "ibm,iic-440spe", "ibm,iic-440gp", "ibm,iic";
+                               reg = <0xf0000500 0x00000014>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <0x3 0x4>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                                rtc@68 {
+                                        compatible = "stm,m41t00";
+                                        reg = <0x68>;
+                                };
+                       };
+
+                       EMAC0: ethernet@f0000800 {
+                               linux,network-index = <0x0>;
+                               device_type = "network";
+                               compatible = "ibm,emac-440spe", "ibm,emac4";
+                               interrupt-parent = <&UIC1>;
+                               interrupts = <0x1c 0x4 0x1d 0x4>;
+                               reg = <0xf0000800 0x00000074>;
+                               local-mac-address = [000000000000];
+                               mal-device = <&MAL0>;
+                               mal-tx-channel = <0>;
+                               mal-rx-channel = <0>;
+                               cell-index = <0>;
+                               max-frame-size = <9000>;
+                               rx-fifo-size = <4096>;
+                               tx-fifo-size = <2048>;
+                               phy-mode = "gmii";
+                               phy-map = <0x00000000>;
+                               has-inverted-stacr-oc;
+                               has-new-stacr-staopc;
+                       };
+               };
+
+               PCIX0: pci@c0ec00000 {
+                       device_type = "pci";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       compatible = "ibm,plb-pcix-440spe", "ibm,plb-pcix";
+                       primary;
+                       large-inbound-windows;
+                       enable-msi-hole;
+                       reg = <0x0000000c 0x0ec00000 0x00000008   /* Config space access */
+                              0x00000000 0x00000000 0x00000000   /* no IACK cycles */
+                              0x0000000c 0x0ed00000 0x00000004   /* Special cycles */
+                              0x0000000c 0x0ec80000 0x00000100   /* Internal registers */
+                              0x0000000c 0x0ec80100 0x000000fc>; /* Internal messaging registers */
+
+                       /* Outbound ranges, one memory and one IO,
+                        * later cannot be changed
+                        */
+                       ranges = <0x02000000 0x00000000 0x80000000 0x0000000d 0x80000000 0x00000000 0x80000000
+                                 0x01000000 0x00000000 0x00000000 0x0000000c 0x08000000 0x00000000 0x00010000>;
+
+                       /* Inbound 4GB range starting at 0 */
+                       dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>;
+
+                       /* This drives busses 0 to 0xf */
+                       bus-range = <0x0 0xf>;
+
+                       /* PCI-X interrupt (SM502) is routed to extIRQ10 (UIC1, 19) */
+                       interrupt-map-mask = <0x0 0x0 0x0 0x0>;
+                       interrupt-map = <0x0 0x0 0x0 0x0 &UIC1 19 0x8>;
+               };
+
+               PCIE0: pciex@d00000000 {
+                       device_type = "pci";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       compatible = "ibm,plb-pciex-440spe", "ibm,plb-pciex";
+                       primary;
+                       port = <0x0>; /* port number */
+                       reg = <0x0000000d 0x00000000 0x20000000 /* Config space access */
+                              0x0000000c 0x10000000 0x00001000>;       /* Registers */
+                       dcr-reg = <0x100 0x020>;
+                       sdr-base = <0x300>;
+
+                       /* Outbound ranges, one memory and one IO,
+                        * later cannot be changed
+                        */
+                       ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000
+                                 0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>;
+
+                       /* Inbound 4GB range starting at 0 */
+                       dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>;
+
+                       /* This drives busses 0x10 to 0x1f */
+                       bus-range = <0x10 0x1f>;
+
+                       /* Legacy interrupts (note the weird polarity, the bridge seems
+                        * to invert PCIe legacy interrupts).
+                        * We are de-swizzling here because the numbers are actually for
+                        * port of the root complex virtual P2P bridge. But I want
+                        * to avoid putting a node for it in the tree, so the numbers
+                        * below are basically de-swizzled numbers.
+                        * The real slot is on idsel 0, so the swizzling is 1:1
+                        */
+                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+                       interrupt-map = <
+                               0x0 0x0 0x0 0x1 &UIC3 0x0 0x4 /* swizzled int A */
+                               0x0 0x0 0x0 0x2 &UIC3 0x1 0x4 /* swizzled int B */
+                               0x0 0x0 0x0 0x3 &UIC3 0x2 0x4 /* swizzled int C */
+                               0x0 0x0 0x0 0x4 &UIC3 0x3 0x4 /* swizzled int D */>;
+               };
+
+               PCIE1: pciex@d20000000 {
+                       device_type = "pci";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       compatible = "ibm,plb-pciex-440spe", "ibm,plb-pciex";
+                       primary;
+                       port = <0x1>; /* port number */
+                       reg = <0x0000000d 0x20000000 0x20000000 /* Config space access */
+                              0x0000000c 0x10001000 0x00001000>;       /* Registers */
+                       dcr-reg = <0x120 0x020>;
+                       sdr-base = <0x340>;
+
+                       /* Outbound ranges, one memory and one IO,
+                        * later cannot be changed
+                        */
+                       ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000
+                                 0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>;
+
+                       /* Inbound 4GB range starting at 0 */
+                       dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x1 0x00000000>;
+
+                       /* This drives busses 0x20 to 0x2f */
+                       bus-range = <0x20 0x2f>;
+
+                       /* Legacy interrupts (note the weird polarity, the bridge seems
+                        * to invert PCIe legacy interrupts).
+                        * We are de-swizzling here because the numbers are actually for
+                        * port of the root complex virtual P2P bridge. But I want
+                        * to avoid putting a node for it in the tree, so the numbers
+                        * below are basically de-swizzled numbers.
+                        * The real slot is on idsel 0, so the swizzling is 1:1
+                        */
+                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+                       interrupt-map = <
+                               0x0 0x0 0x0 0x1 &UIC3 0x4 0x4 /* swizzled int A */
+                               0x0 0x0 0x0 0x2 &UIC3 0x5 0x4 /* swizzled int B */
+                               0x0 0x0 0x0 0x3 &UIC3 0x6 0x4 /* swizzled int C */
+                               0x0 0x0 0x0 0x4 &UIC3 0x7 0x4 /* swizzled int D */>;
+               };
+
+               I2O: i2o@400100000 {
+                       compatible = "ibm,i2o-440spe";
+                       reg = <0x00000004 0x00100000 0x100>;
+                       dcr-reg = <0x060 0x020>;
+               };
+
+               DMA0: dma0@400100100 {
+                       compatible = "ibm,dma-440spe";
+                       cell-index = <0>;
+                       reg = <0x00000004 0x00100100 0x100>;
+                       dcr-reg = <0x060 0x020>;
+                       interrupt-parent = <&DMA0>;
+                       interrupts = <0 1>;
+                       #interrupt-cells = <1>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = <
+                               0 &UIC0 0x14 4
+                               1 &UIC1 0x16 4>;
+               };
+
+               DMA1: dma1@400100200 {
+                       compatible = "ibm,dma-440spe";
+                       cell-index = <1>;
+                       reg = <0x00000004 0x00100200 0x100>;
+                       dcr-reg = <0x060 0x020>;
+                       interrupt-parent = <&DMA1>;
+                       interrupts = <0 1>;
+                       #interrupt-cells = <1>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = <
+                               0 &UIC0 0x16 4
+                               1 &UIC1 0x16 4>;
+               };
+
+               xor-accel@400200000 {
+                       compatible = "amcc,xor-accelerator";
+                       reg = <0x00000004 0x00200000 0x400>;
+                       interrupt-parent = <&UIC1>;
+                       interrupts = <0x1f 4>;
+               };
+       };
+
+       chosen {
+               linux,stdout-path = "/plb/opb/serial@f0000200";
+       };
+};
index 8cf2c0c88c0584d5ced42fe26cde120bcdba7580..7c3be5e45748e4abdaa2605b70c68fe851c50b21 100644 (file)
@@ -44,6 +44,7 @@
                        d-cache-size = <32768>;
                        dcr-controller;
                        dcr-access-method = "native";
+                       reset-type = <2>;       /* Use chip-reset */
                };
        };
 
index 82ff2b13bc37905deebbda9816616a2d92a0ee61..179a1785d6454dbfdda53a532474dfa4c5c5340e 100644 (file)
                        compatible = "fsl,mpc5200-gpio";
                        reg = <0xb00 0x40>;
                        interrupts = <1 7 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
                };
 
                gpio@c00 {
                        compatible = "fsl,mpc5200-gpio-wkup";
                        reg = <0xc00 0x40>;
                        interrupts = <1 8 0 0 3 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
                };
 
                spi@f00 {
                        reg = <0x3000 0x400>;   // fec range, since we need to setup fec interrupts
                        interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
 
-                       phy0: ethernet-phy@1 {
-                               reg = <1>;
+                       phy0: ethernet-phy@0 {
+                               reg = <0>;
                        };
                };
 
                        compatible = "fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d40 0x40>;
                        interrupts = <2 16 0>;
+
+                       eeprom@50 {
+                               compatible = "atmel,24c02";
+                               reg = <0x50>;
+                       };
                };
+
                sram@8000 {
                        compatible = "fsl,mpc5200-sram";
                        reg = <0x8000 0x4000>;
                          0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
                          0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
        };
+
+       localbus {
+               compatible = "fsl,mpc5200-lpb","simple-bus";
+               #address-cells = <2>;
+               #size-cells = <1>;
+
+               ranges = <0 0 0xff000000 0x01000000>;
+
+               flash@0,0 {
+                       compatible = "amd,am29lv652d", "cfi-flash";
+                       reg = <0 0 0x01000000>;
+                       bank-width = <1>;
+               };
+       };
 };
index e45a63be3a8618f73b0ed0921e81cf4d755dd2ae..59702ace900f9dc07a447e51fe34bb481b83864e 100644 (file)
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d40 0x40>;
                        interrupts = <2 16 0>;
+
+                       eeprom@50 {
+                               compatible = "atmel,24c02";
+                               reg = <0x50>;
+                       };
                };
 
                sram@8000 {
index 4173af387c6355ae8c50aa4d7141d98ad0901e76..0f5262452682ebf6e25719b90efee5f6d5a92aa4 100644 (file)
        aliases {
                ethernet0 = &enet0;
                ethernet1 = &enet1;
-/*
                ethernet2 = &enet2;
                ethernet3 = &enet3;
-*/
                serial0 = &serial0;
                serial1 = &serial1;
                pci0 = &pci0;
                        };
                };
 
-/* eTSEC 3/4 are currently broken
                enet2: ethernet@26000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
                                };
                        };
                };
- */
 
                serial0: serial@4500 {
                        cell-index = <0>;
index 5bd1011fde960d083d4ab496736eaf48388e0221..3375c2ab0c32862ca9111a5e9b08267c5a089ba6 100644 (file)
                        clock-frequency = <0>;
                };
 
+               msi@41600 {
+                       compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
+                       reg = <0x41600 0x80>;
+                       msi-available-ranges = <0 0x80>;
+                       interrupts = <
+                               0xe0 0
+                               0xe1 0
+                               0xe2 0
+                               0xe3 0>;
+                       interrupt-parent = <&mpic>;
+               };
+
                global-utilities@e0000 {        //global utilities block
                        compatible = "fsl,mpc8572-guts";
                        reg = <0xe0000 0x1000>;
                        protected-sources = <
                        31 32 33 37 38 39       /* enet2 enet3 */
                        76 77 78 79 26 42       /* dma2 pci2 serial*/
-                       0xe0 0xe1 0xe2 0xe3     /* msi */
-                       0xe4 0xe5 0xe6 0xe7
+                       0xe4 0xe5 0xe6 0xe7     /* msi */
                        >;
                };
        };
index 0efc3456e2976e6ee67673aabb5232fe69589b34..e7b477f6a3fea32d68aaceb623469c9f8bd0053a 100644 (file)
                msi@41600 {
                        compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
                        reg = <0x41600 0x80>;
-                       msi-available-ranges = <0 0x100>;
+                       msi-available-ranges = <0x80 0x80>;
                        interrupts = <
-                               0xe0 0
-                               0xe1 0
-                               0xe2 0
-                               0xe3 0
                                0xe4 0
                                0xe5 0
                                0xe6 0
                        0x1 0x2 0x3 0x4         /* pci slot */
                        0x9 0xa 0xb 0xc         /* usb */
                        0x6 0x7 0xe 0x5         /* Audio elgacy SATA */
+                       0xe0 0xe1 0xe2 0xe3     /* msi */
                        >;
                };
        };
diff --git a/arch/powerpc/boot/dts/p1021mds.dts b/arch/powerpc/boot/dts/p1021mds.dts
new file mode 100644 (file)
index 0000000..7fad2df
--- /dev/null
@@ -0,0 +1,698 @@
+/*
+ * P1021 MDS Device Tree Source
+ *
+ * Copyright 2010 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+/ {
+       model = "fsl,P1021";
+       compatible = "fsl,P1021MDS";
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       aliases {
+               serial0 = &serial0;
+               serial1 = &serial1;
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               ethernet2 = &enet2;
+               ethernet3 = &enet3;
+               ethernet4 = &enet4;
+               pci0 = &pci0;
+               pci1 = &pci1;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,P1021@0 {
+                       device_type = "cpu";
+                       reg = <0x0>;
+                       next-level-cache = <&L2>;
+               };
+
+               PowerPC,P1021@1 {
+                       device_type = "cpu";
+                       reg = <0x1>;
+                       next-level-cache = <&L2>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+       };
+
+       localbus@ffe05000 {
+               #address-cells = <2>;
+               #size-cells = <1>;
+               compatible = "fsl,p1021-elbc", "fsl,elbc", "simple-bus";
+               reg = <0 0xffe05000 0 0x1000>;
+               interrupts = <19 2>;
+               interrupt-parent = <&mpic>;
+
+               /* NAND Flash, BCSR, PMC0/1*/
+               ranges = <0x0 0x0 0x0 0xfc000000 0x02000000
+                         0x1 0x0 0x0 0xf8000000 0x00008000
+                         0x2 0x0 0x0 0xf8010000 0x00020000
+                         0x3 0x0 0x0 0xf8020000 0x00020000>;
+
+               nand@0,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,p1021-fcm-nand",
+                                    "fsl,elbc-fcm-nand";
+                       reg = <0x0 0x0 0x40000>;
+
+                       partition@0 {
+                               /* This location must not be altered  */
+                               /* 1MB for u-boot Bootloader Image */
+                               reg = <0x0 0x00100000>;
+                               label = "NAND (RO) U-Boot Image";
+                               read-only;
+                       };
+
+                       partition@100000 {
+                               /* 1MB for DTB Image */
+                               reg = <0x00100000 0x00100000>;
+                               label = "NAND (RO) DTB Image";
+                               read-only;
+                       };
+
+                       partition@200000 {
+                               /* 4MB for Linux Kernel Image */
+                               reg = <0x00200000 0x00400000>;
+                               label = "NAND (RO) Linux Kernel Image";
+                               read-only;
+                       };
+
+                       partition@600000 {
+                               /* 5MB for Compressed Root file System Image */
+                               reg = <0x00600000 0x00500000>;
+                               label = "NAND (RO) Compressed RFS Image";
+                               read-only;
+                       };
+
+                       partition@b00000 {
+                               /* 6MB for JFFS2 based Root file System */
+                               reg = <0x00a00000 0x00600000>;
+                               label = "NAND (RW) JFFS2 Root File System";
+                       };
+
+                       partition@1100000 {
+                               /* 14MB for JFFS2 based Root file System */
+                               reg = <0x01100000 0x00e00000>;
+                               label = "NAND (RW) Writable User area";
+                       };
+
+                       partition@1f00000 {
+                               /* 1MB for microcode */
+                               reg = <0x01f00000 0x00100000>;
+                               label = "NAND (RO) QE Ucode";
+                               read-only;
+                       };
+               };
+
+               bcsr@1,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,p1021mds-bcsr";
+                       reg = <1 0 0x8000>;
+                       ranges = <0 1 0 0x8000>;
+               };
+
+               pib@2,0 {
+                       compatible = "fsl,p1021mds-pib";
+                       reg = <2 0 0x10000>;
+               };
+
+               pib@3,0 {
+                       compatible = "fsl,p1021mds-pib";
+                       reg = <3 0 0x10000>;
+               };
+       };
+
+       soc@ffe00000 {
+
+               #address-cells = <1>;
+               #size-cells = <1>;
+               device_type = "soc";
+               compatible = "fsl,p1021-immr", "simple-bus";
+               ranges = <0x0  0x0 0xffe00000 0x100000>;
+               bus-frequency = <0>;            // Filled out by uboot.
+
+               ecm-law@0 {
+                       compatible = "fsl,ecm-law";
+                       reg = <0x0 0x1000>;
+                       fsl,num-laws = <12>;
+               };
+
+               ecm@1000 {
+                       compatible = "fsl,p1021-ecm", "fsl,ecm";
+                       reg = <0x1000 0x1000>;
+                       interrupts = <16 2>;
+                       interrupt-parent = <&mpic>;
+               };
+
+               memory-controller@2000 {
+                       compatible = "fsl,p1021-memory-controller";
+                       reg = <0x2000 0x1000>;
+                       interrupt-parent = <&mpic>;
+                       interrupts = <16 2>;
+               };
+
+               i2c@3000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
+                       compatible = "fsl-i2c";
+                       reg = <0x3000 0x100>;
+                       interrupts = <43 2>;
+                       interrupt-parent = <&mpic>;
+                       dfsrr;
+                       rtc@68 {
+                               compatible = "dallas,ds1374";
+                               reg = <0x68>;
+                       };
+               };
+
+               i2c@3100 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
+                       compatible = "fsl-i2c";
+                       reg = <0x3100 0x100>;
+                       interrupts = <43 2>;
+                       interrupt-parent = <&mpic>;
+                       dfsrr;
+               };
+
+               serial0: serial@4500 {
+                       cell-index = <0>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x4500 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <42 2>;
+                       interrupt-parent = <&mpic>;
+               };
+
+               serial1: serial@4600 {
+                       cell-index = <1>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x4600 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <42 2>;
+                       interrupt-parent = <&mpic>;
+               };
+
+               spi@7000 {
+                       cell-index = <0>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,espi";
+                       reg = <0x7000 0x1000>;
+                       interrupts = <59 0x2>;
+                       interrupt-parent = <&mpic>;
+                       espi,num-ss-bits = <4>;
+                       mode = "cpu";
+
+                       fsl_m25p80@0 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "fsl,espi-flash";
+                               reg = <0>;
+                               linux,modalias = "fsl_m25p80";
+                               spi-max-frequency = <40000000>; /* input clock */
+                               partition@u-boot {
+                                       label = "u-boot-spi";
+                                       reg = <0x00000000 0x00100000>;
+                                       read-only;
+                               };
+                               partition@kernel {
+                                       label = "kernel-spi";
+                                       reg = <0x00100000 0x00500000>;
+                                       read-only;
+                               };
+                               partition@dtb {
+                                       label = "dtb-spi";
+                                       reg = <0x00600000 0x00100000>;
+                                       read-only;
+                               };
+                               partition@fs {
+                                       label = "file system-spi";
+                                       reg = <0x00700000 0x00900000>;
+                               };
+                       };
+               };
+
+               gpio: gpio-controller@f000 {
+                       #gpio-cells = <2>;
+                       compatible = "fsl,mpc8572-gpio";
+                       reg = <0xf000 0x100>;
+                       interrupts = <47 0x2>;
+                       interrupt-parent = <&mpic>;
+                       gpio-controller;
+               };
+
+               L2: l2-cache-controller@20000 {
+                       compatible = "fsl,p1021-l2-cache-controller";
+                       reg = <0x20000 0x1000>;
+                       cache-line-size = <32>; // 32 bytes
+                       cache-size = <0x40000>; // L2,256K
+                       interrupt-parent = <&mpic>;
+                       interrupts = <16 2>;
+               };
+
+               dma@21300 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,eloplus-dma";
+                       reg = <0x21300 0x4>;
+                       ranges = <0x0 0x21100 0x200>;
+                       cell-index = <0>;
+                       dma-channel@0 {
+                               compatible = "fsl,eloplus-dma-channel";
+                               reg = <0x0 0x80>;
+                               cell-index = <0>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <20 2>;
+                       };
+                       dma-channel@80 {
+                               compatible = "fsl,eloplus-dma-channel";
+                               reg = <0x80 0x80>;
+                               cell-index = <1>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <21 2>;
+                       };
+                       dma-channel@100 {
+                               compatible = "fsl,eloplus-dma-channel";
+                               reg = <0x100 0x80>;
+                               cell-index = <2>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <22 2>;
+                       };
+                       dma-channel@180 {
+                               compatible = "fsl,eloplus-dma-channel";
+                               reg = <0x180 0x80>;
+                               cell-index = <3>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <23 2>;
+                       };
+               };
+
+               usb@22000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl-usb2-dr";
+                       reg = <0x22000 0x1000>;
+                       interrupt-parent = <&mpic>;
+                       interrupts = <28 0x2>;
+                       phy_type = "ulpi";
+               };
+
+                mdio@24000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,etsec2-mdio";
+                       reg = <0x24000 0x1000 0xb0030 0x4>;
+
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&mpic>;
+                               interrupts = <1 1>;
+                               reg = <0x0>;
+                       };
+                       phy1: ethernet-phy@1 {
+                               interrupt-parent = <&mpic>;
+                               interrupts = <2 1>;
+                               reg = <0x1>;
+                       };
+                       phy4: ethernet-phy@4 {
+                               interrupt-parent = <&mpic>;
+                               reg = <0x4>;
+                       };
+               };
+
+               mdio@25000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,etsec2-tbi";
+                       reg = <0x25000 0x1000 0xb1030 0x4>;
+                       tbi0: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet0: ethernet@B0000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       cell-index = <0>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "fsl,etsec2";
+                       fsl,num_rx_queues = <0x8>;
+                       fsl,num_tx_queues = <0x8>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy0>;
+                       phy-connection-type = "rgmii-id";
+                       queue-group@0{
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0xB0000 0x1000>;
+                               interrupts = <29 2 30 2 34 2>;
+                       };
+                       queue-group@1{
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0xB4000 0x1000>;
+                               interrupts = <17 2 18 2 24 2>;
+                       };
+               };
+
+               enet1: ethernet@B1000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       cell-index = <0>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "fsl,etsec2";
+                       fsl,num_rx_queues = <0x8>;
+                       fsl,num_tx_queues = <0x8>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy4>;
+                       tbi-handle = <&tbi0>;
+                       phy-connection-type = "sgmii";
+                       queue-group@0{
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0xB1000 0x1000>;
+                               interrupts = <35 2 36 2 40 2>;
+                       };
+                       queue-group@1{
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0xB5000 0x1000>;
+                               interrupts = <51 2 52 2 67 2>;
+                       };
+               };
+
+               enet2: ethernet@B2000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       cell-index = <0>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "fsl,etsec2";
+                       fsl,num_rx_queues = <0x8>;
+                       fsl,num_tx_queues = <0x8>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy1>;
+                       phy-connection-type = "rgmii-id";
+                       queue-group@0{
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0xB2000 0x1000>;
+                               interrupts = <31 2 32 2 33 2>;
+                       };
+                       queue-group@1{
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0xB6000 0x1000>;
+                               interrupts = <25 2 26 2 27 2>;
+                       };
+               };
+
+               sdhci@2e000 {
+                       compatible = "fsl,p1021-esdhc", "fsl,esdhc";
+                       reg = <0x2e000 0x1000>;
+                       interrupts = <72 0x2>;
+                       interrupt-parent = <&mpic>;
+                       /* Filled in by U-Boot */
+                       clock-frequency = <0>;
+               };
+
+               crypto@30000 {
+                       compatible = "fsl,sec3.3", "fsl,sec3.1",
+                                    "fsl,sec3.0", "fsl,sec2.4",
+                                    "fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0";
+                       reg = <0x30000 0x10000>;
+                       interrupts = <45 2 58 2>;
+                       interrupt-parent = <&mpic>;
+                       fsl,num-channels = <4>;
+                       fsl,channel-fifo-len = <24>;
+                       fsl,exec-units-mask = <0x97c>;
+                       fsl,descriptor-types-mask = <0x3a30abf>;
+               };
+
+               mpic: pic@40000 {
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <0x40000 0x40000>;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+               };
+
+               msi@41600 {
+                       compatible = "fsl,p1021-msi", "fsl,mpic-msi";
+                       reg = <0x41600 0x80>;
+                       msi-available-ranges = <0 0x100>;
+                       interrupts = <
+                               0xe0 0
+                               0xe1 0
+                               0xe2 0
+                               0xe3 0
+                               0xe4 0
+                               0xe5 0
+                               0xe6 0
+                               0xe7 0>;
+                       interrupt-parent = <&mpic>;
+               };
+
+               global-utilities@e0000 {        //global utilities block
+                       compatible = "fsl,p1021-guts";
+                       reg = <0xe0000 0x1000>;
+                       fsl,has-rstcr;
+               };
+
+               par_io@e0100 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0xe0100 0x60>;
+                       ranges = <0x0 0xe0100 0x60>;
+                       device_type = "par_io";
+                       num-ports = <3>;
+                       pio1: ucc_pin@01 {
+                               pio-map = <
+                       /* port  pin  dir  open_drain  assignment  has_irq */
+                                       0x1  0x13 0x1  0x0  0x1  0x0    /* QE_MUX_MDC */
+                                       0x1  0x14 0x3  0x0  0x1  0x0    /* QE_MUX_MDIO */
+                                       0x0  0x17 0x2  0x0  0x2  0x0    /* CLK12 */
+                                       0x0  0x18 0x2  0x0  0x1  0x0    /* CLK9
+*/
+                                       0x0  0x7  0x1  0x0  0x2  0x0    /* ENET1_TXD0_SER1_TXD0 */
+                                       0x0  0x9  0x1  0x0  0x2  0x0    /* ENET1_TXD1_SER1_TXD1 */
+                                       0x0  0xb  0x1  0x0  0x2  0x0    /* ENET1_TXD2_SER1_TXD2 */
+                                       0x0  0xc  0x1  0x0  0x2  0x0    /* ENET1_TXD3_SER1_TXD3 */
+                                       0x0  0x6  0x2  0x0  0x2  0x0    /* ENET1_RXD0_SER1_RXD0 */
+                                       0x0  0xa  0x2  0x0  0x2  0x0    /* ENET1_RXD1_SER1_RXD1 */
+                                       0x0  0xe  0x2  0x0  0x2  0x0    /* ENET1_RXD2_SER1_RXD2 */
+                                       0x0  0xf  0x2  0x0  0x2  0x0    /* ENET1_RXD3_SER1_RXD3 */
+                                       0x0  0x5  0x1  0x0  0x2  0x0    /* ENET1_TX_EN_SER1_RTS_B */
+                                       0x0  0xd  0x1  0x0  0x2  0x0    /* ENET1_TX_ER */
+                                       0x0  0x4  0x2  0x0  0x2  0x0    /* ENET1_RX_DV_SER1_CTS_B */
+                                       0x0  0x8  0x2  0x0  0x2  0x0    /* ENET1_RX_ER_SER1_CD_B */
+                                       0x0  0x11 0x2  0x0  0x2  0x0    /* ENET1_CRS */
+                                       0x0  0x10 0x2  0x0  0x2  0x0>;    /* ENET1_COL */
+                       };
+
+                       pio2: ucc_pin@02 {
+                               pio-map = <
+                       /* port  pin  dir  open_drain  assignment  has_irq */
+                                       0x1  0x13 0x1  0x0  0x1  0x0    /* QE_MUX_MDC */
+                                       0x1  0x14 0x3  0x0  0x1  0x0    /* QE_MUX_MDIO */
+                                       0x1  0xb  0x2  0x0  0x1  0x0    /* CLK13 */
+                                       0x1  0x7  0x1  0x0  0x2  0x0    /* ENET5_TXD0_SER5_TXD0 */
+                                       0x1  0xa  0x1  0x0  0x2  0x0    /* ENET5_TXD1_SER5_TXD1 */
+                                       0x1  0x6  0x2  0x0  0x2  0x0    /* ENET5_RXD0_SER5_RXD0 */
+                                       0x1  0x9  0x2  0x0  0x2  0x0    /* ENET5_RXD1_SER5_RXD1 */
+                                       0x1  0x5  0x1  0x0  0x2  0x0    /* ENET5_TX_EN_SER5_RTS_B */
+                                       0x1  0x4  0x2  0x0  0x2  0x0    /* ENET5_RX_DV_SER5_CTS_B */
+                                       0x1  0x8  0x2  0x0  0x2  0x0>;    /* ENET5_RX_ER_SER5_CD_B */
+                       };
+               };
+       };
+
+       pci0: pcie@ffe09000 {
+               compatible = "fsl,mpc8548-pcie";
+               device_type = "pci";
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               reg = <0 0xffe09000 0 0x1000>;
+               bus-range = <0 255>;
+               ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+               clock-frequency = <33333333>;
+               interrupt-parent = <&mpic>;
+               interrupts = <16 2>;
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <
+                       /* IDSEL 0x0 */
+                       0000 0 0 1 &mpic 4 1
+                       0000 0 0 2 &mpic 5 1
+                       0000 0 0 3 &mpic 6 1
+                       0000 0 0 4 &mpic 7 1
+                       >;
+               pcie@0 {
+                       reg = <0x0 0x0 0x0 0x0 0x0>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       ranges = <0x2000000 0x0 0xa0000000
+                                 0x2000000 0x0 0xa0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci1: pcie@ffe0a000 {
+               compatible = "fsl,mpc8548-pcie";
+               device_type = "pci";
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               reg = <0 0xffe0a000 0 0x1000>;
+               bus-range = <0 255>;
+               ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
+               clock-frequency = <33333333>;
+               interrupt-parent = <&mpic>;
+               interrupts = <16 2>;
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <
+                       /* IDSEL 0x0 */
+                       0000 0 0 1 &mpic 0 1
+                       0000 0 0 2 &mpic 1 1
+                       0000 0 0 3 &mpic 2 1
+                       0000 0 0 4 &mpic 3 1
+                       >;
+               pcie@0 {
+                       reg = <0x0 0x0 0x0 0x0 0x0>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       ranges = <0x2000000 0x0 0xc0000000
+                                 0x2000000 0x0 0xc0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       qe@ffe80000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               device_type = "qe";
+               compatible = "fsl,qe";
+               ranges = <0x0 0x0 0xffe80000 0x40000>;
+               reg = <0 0xffe80000 0 0x480>;
+               brg-frequency = <0>;
+               bus-frequency = <0>;
+               fsl,qe-num-riscs = <1>;
+               fsl,qe-num-snums = <28>;
+
+               qeic: interrupt-controller@80 {
+                       interrupt-controller;
+                       compatible = "fsl,qe-ic";
+                       #address-cells = <0>;
+                       #interrupt-cells = <1>;
+                       reg = <0x80 0x80>;
+                       interrupts = <63 2 60 2>; //high:47 low:44
+                       interrupt-parent = <&mpic>;
+               };
+
+               enet3: ucc@2000 {
+                       device_type = "network";
+                       compatible = "ucc_geth";
+                       cell-index = <1>;
+                       reg = <0x2000 0x200>;
+                       interrupts = <32>;
+                       interrupt-parent = <&qeic>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       rx-clock-name = "clk12";
+                       tx-clock-name = "clk9";
+                       pio-handle = <&pio1>;
+                       phy-handle = <&qe_phy0>;
+                       phy-connection-type = "mii";
+               };
+
+               mdio@2120 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x2120 0x18>;
+                       compatible = "fsl,ucc-mdio";
+
+                       qe_phy0: ethernet-phy@0 {
+                               interrupt-parent = <&mpic>;
+                               interrupts = <4 1>;
+                               reg = <0x0>;
+                               device_type = "ethernet-phy";
+                       };
+                       qe_phy1: ethernet-phy@03 {
+                               interrupt-parent = <&mpic>;
+                               interrupts = <5 1>;
+                               reg = <0x3>;
+                               device_type = "ethernet-phy";
+                       };
+                       tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet4: ucc@2400 {
+                       device_type = "network";
+                       compatible = "ucc_geth";
+                       cell-index = <5>;
+                       reg = <0x2400 0x200>;
+                       interrupts = <40>;
+                       interrupt-parent = <&qeic>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       rx-clock-name = "none";
+                       tx-clock-name = "clk13";
+                       pio-handle = <&pio2>;
+                       phy-handle = <&qe_phy1>;
+                       phy-connection-type = "rmii";
+               };
+
+               muram@10000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,qe-muram", "fsl,cpm-muram";
+                       ranges = <0x0 0x10000 0x6000>;
+
+                       data-only@0 {
+                               compatible = "fsl,qe-muram-data",
+                               "fsl,cpm-muram-data";
+                               reg = <0x0 0x6000>;
+                       };
+               };
+       };
+};
index d2af32e2bf7a78e83d1b700697f5aff8599b7cf6..81636c01d90652d2bc9082a872c4ba1594a0ac5d 100644 (file)
                                has-inverted-stacr-oc;
                                has-new-stacr-staopc;
                        };
+               };
+               PCIE0: pciex@d00000000 {
+                       device_type = "pci";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       compatible = "ibm,plb-pciex-460sx", "ibm,plb-pciex";
+                       primary;
+                       port = <0x0>; /* port number */
+                       reg = <0x0000000d 0x00000000 0x20000000 /* Config space access */
+                              0x0000000c 0x10000000 0x00001000>;       /* Registers */
+                       dcr-reg = <0x100 0x020>;
+                       sdr-base = <0x300>;
+
+                       /* Outbound ranges, one memory and one IO,
+                        * later cannot be changed
+                        */
+                       ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000
+                                 0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>;
+
+                       /* Inbound 2GB range starting at 0 */
+                       dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
 
+                       /* This drives busses 10 to 0x1f */
+                       bus-range = <0x10 0x1f>;
+
+                       /* Legacy interrupts (note the weird polarity, the bridge seems
+                        * to invert PCIe legacy interrupts).
+                        * We are de-swizzling here because the numbers are actually for
+                        * port of the root complex virtual P2P bridge. But I want
+                        * to avoid putting a node for it in the tree, so the numbers
+                        * below are basically de-swizzled numbers.
+                        * The real slot is on idsel 0, so the swizzling is 1:1
+                        */
+                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+                       interrupt-map = <
+                               0x0 0x0 0x0 0x1 &UIC3 0x0 0x4 /* swizzled int A */
+                               0x0 0x0 0x0 0x2 &UIC3 0x1 0x4 /* swizzled int B */
+                               0x0 0x0 0x0 0x3 &UIC3 0x2 0x4 /* swizzled int C */
+                               0x0 0x0 0x0 0x4 &UIC3 0x3 0x4 /* swizzled int D */>;
+               };
+
+               PCIE1: pciex@d20000000 {
+                       device_type = "pci";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       compatible = "ibm,plb-pciex-460sx", "ibm,plb-pciex";
+                       primary;
+                       port = <0x1>; /* port number */
+                       reg = <0x0000000d 0x20000000 0x20000000 /* Config space access */
+                              0x0000000c 0x10001000 0x00001000>;       /* Registers */
+                       dcr-reg = <0x120 0x020>;
+                       sdr-base = <0x340>;
+
+                       /* Outbound ranges, one memory and one IO,
+                        * later cannot be changed
+                        */
+                       ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000
+                                 0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>;
+
+                       /* Inbound 2GB range starting at 0 */
+                       dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
+
+                       /* This drives busses 10 to 0x1f */
+                       bus-range = <0x20 0x2f>;
+
+                       /* Legacy interrupts (note the weird polarity, the bridge seems
+                        * to invert PCIe legacy interrupts).
+                        * We are de-swizzling here because the numbers are actually for
+                        * port of the root complex virtual P2P bridge. But I want
+                        * to avoid putting a node for it in the tree, so the numbers
+                        * below are basically de-swizzled numbers.
+                        * The real slot is on idsel 0, so the swizzling is 1:1
+                        */
+                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+                       interrupt-map = <
+                               0x0 0x0 0x0 0x1 &UIC3 0x4 0x4 /* swizzled int A */
+                               0x0 0x0 0x0 0x2 &UIC3 0x5 0x4 /* swizzled int B */
+                               0x0 0x0 0x0 0x3 &UIC3 0x6 0x4 /* swizzled int C */
+                               0x0 0x0 0x0 0x4 &UIC3 0x7 0x4 /* swizzled int D */>;
+               };
+
+               PCIE2: pciex@d40000000 {
+                       device_type = "pci";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       compatible = "ibm,plb-pciex-460sx", "ibm,plb-pciex";
+                       primary;
+                       port = <0x2>; /* port number */
+                       reg = <0x0000000d 0x40000000 0x20000000 /* Config space access */
+                              0x0000000c 0x10002000 0x00001000>;       /* Registers */
+                       dcr-reg = <0x140 0x020>;
+                       sdr-base = <0x370>;
+
+                       /* Outbound ranges, one memory and one IO,
+                        * later cannot be changed
+                        */
+                       ranges = <0x02000000 0x00000000 0x80000000 0x0000000f 0x00000000 0x00000000 0x80000000
+                                 0x01000000 0x00000000 0x00000000 0x0000000f 0x80020000 0x00000000 0x00010000>;
+
+                       /* Inbound 2GB range starting at 0 */
+                       dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
+
+                       /* This drives busses 10 to 0x1f */
+                       bus-range = <0x30 0x3f>;
+
+                       /* Legacy interrupts (note the weird polarity, the bridge seems
+                        * to invert PCIe legacy interrupts).
+                        * We are de-swizzling here because the numbers are actually for
+                        * port of the root complex virtual P2P bridge. But I want
+                        * to avoid putting a node for it in the tree, so the numbers
+                        * below are basically de-swizzled numbers.
+                        * The real slot is on idsel 0, so the swizzling is 1:1
+                        */
+                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+                       interrupt-map = <
+                               0x0 0x0 0x0 0x1 &UIC3 0x8 0x4 /* swizzled int A */
+                               0x0 0x0 0x0 0x2 &UIC3 0x9 0x4 /* swizzled int B */
+                               0x0 0x0 0x0 0x3 &UIC3 0xa 0x4 /* swizzled int C */
+                               0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>;
                };
 
        };
+
        chosen {
                linux,stdout-path = "/plb/opb/serial@ef600200";
        };
index 8e95f8d227b94764fe73f397c25ce4ca5b8d0ecd..4aa17b676a3f51f761a4fe279a639142effc51f6 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 918f23fd2b1896b93093172b0527d038225e67a9..9a5f1ab777ed3541103355ce1d708e0e8fb64191 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index f87ef0382280f0695ed21a0ef58f284db4d3e20f..0b452135d1d449c82796eb50a89543c991a0cd09 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 19fbcb0753760b1932bdaee567e79da3cac71277..4d2de0bed60e0d1024fbd5a6db6e345b7801b34c 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index eb41cd695979550e3ec9152f4fa49ab0f7e45c83..a1f3f505e4a76b7d4177a750f44b8b2f7dbf43fa 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 416e79ac0711aeeb4d97ee4cab178de7a571d855..c763135771404d32ea809d911a289420318137de 100644 (file)
@@ -77,8 +77,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index bfff0eae39d29bf01c4af98f65a0aa40f14f3793..6597b2f1d1a80ad09a2a7390846dcd70fe854835 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 1f6d0490e28d10582be09dc89065ac608e8d66b7..2d3dfb55fbed3af160b298271116ef37079f92a2 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=32
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 788faac6c27a0d4c213f9308ef29fdd8d2fc8348..51a00c46df195a9cfab1ac851659c6489aee8eaa 100644 (file)
@@ -102,8 +102,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 4ef8bcab61f838dc8298dd5eea4790ddff1aa15b..1028b1bfb6022170f3022830c2f9ec737747d83d 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=32
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index ca17b1496e32c82adc26d1438bc283804dabc8b2..69f5633cbd4f20d51a0b5fd535e6db3cab475e7f 100644 (file)
@@ -101,8 +101,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index e3149bade0b25c6d101eb081ef58e568752baf03..dcd859c8b4a6487a26fa73c65b137958e905f056 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=32
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/icon_defconfig b/arch/powerpc/configs/44x/icon_defconfig
new file mode 100644 (file)
index 0000000..277f88c
--- /dev/null
@@ -0,0 +1,1451 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.34-rc7
+# Fri May 21 17:40:22 2010
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+# CONFIG_PPC_BOOK3S_32 is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+CONFIG_44x=y
+# CONFIG_E200 is not set
+CONFIG_4xx=y
+CONFIG_BOOKE=y
+CONFIG_PTE_64BIT=y
+CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
+CONFIG_PPC_MMU_NOHASH_32=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_NR_IRQS=512
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
+# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_PPC_DCR_NATIVE=y
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_DCR=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_PPC_ADV_DEBUG_REGS=y
+CONFIG_PPC_ADV_DEBUG_IACS=4
+CONFIG_PPC_ADV_DEBUG_DACS=2
+CONFIG_PPC_ADV_DEBUG_DVCS=2
+CONFIG_PPC_ADV_DEBUG_DAC_RANGE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES 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_LZO is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+# CONFIG_LOGBUFFER is not set
+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_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=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_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# 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_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# 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=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# 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=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# 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=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+CONFIG_PPC4xx_PCI_EXPRESS=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_BAMBOO is not set
+# CONFIG_EBONY is not set
+# CONFIG_SAM440EP is not set
+# CONFIG_SEQUOIA is not set
+# CONFIG_TAISHAN is not set
+# CONFIG_KATMAI is not set
+# CONFIG_RAINIER is not set
+# CONFIG_WARP is not set
+# CONFIG_ARCHES is not set
+# CONFIG_CANYONLANDS is not set
+# CONFIG_GLACIER is not set
+# CONFIG_REDWOOD is not set
+# CONFIG_EIGER is not set
+# CONFIG_YOSEMITE is not set
+CONFIG_ICON=y
+# CONFIG_XILINX_VIRTEX440_GENERIC_BOARD is not set
+CONFIG_PPC44x_SIMPLE=y
+# CONFIG_PPC4xx_GPIO is not set
+CONFIG_440SPe=y
+CONFIG_STDBINUTILS=y
+# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_MAX_ACTIVE_REGIONS=32
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_ARCH_HAS_NMI_WATCHDOG is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_4xx_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
+# CONFIG_PCIEASPM is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# 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 is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# 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_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 is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# 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_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+# 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_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# 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_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 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 is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_DYNAMIC=y
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=35000
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_XILINX_SYSACE=y
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+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 is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+# 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=y
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_FUSION=y
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+CONFIG_FUSION_SAS=y
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=y
+CONFIG_FUSION_LOGGING=y
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# The newer stack is recommended.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=128
+CONFIG_IBM_NEW_EMAC_TXB=64
+CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+CONFIG_IBM_NEW_EMAC_EMAC4=y
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_ATL2 is not set
+# CONFIG_XILINX_EMACLITE is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_MAX7359 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_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_PS2_ALPS is not set
+# CONFIG_MOUSE_PS2_LOGIPS2PP is not set
+# CONFIG_MOUSE_PS2_SYNAPTICS is not set
+# CONFIG_MOUSE_PS2_TRACKPOINT is not set
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_BOOTCOUNT is not set
+# CONFIG_DISPLAY_PDSP1880 is not set
+# CONFIG_MUCMC52_IO is not set
+# CONFIG_UC101_IO is not set
+# CONFIG_SRAM is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_IBM_IIC=y
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# 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 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY 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
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_88PM860X is not set
+CONFIG_MFD_SM501=y
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+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_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_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+CONFIG_FB_SM501=y
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC 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_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 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
+
+#
+# SPI RTC drivers
+#
+
+#
+# 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_RTC_DRV_GENERIC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING 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=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# 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 is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# 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_JFFS2_FS is not set
+# CONFIG_YAFFS_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 is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS 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 is not set
+CONFIG_MSDOS_PARTITION=y
+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=y
+# 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 is not set
+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=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+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 is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# 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_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_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO 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_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR 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_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+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_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
+CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO 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_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=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 is not set
+# 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=y
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+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 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# 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 is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_CRYPTO_DEV_PPC4XX is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
index af244e1d255e2908dd107b5f97f5aacc44559b18..a2c24d1e051e14b0132146649ffd8827aefe13d5 100644 (file)
@@ -97,8 +97,7 @@ CONFIG_RCU_FANOUT=32
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 8fed3b26af2e39c450b68012121bebbfce6b81c6..3bb55b57077e1fe06f7c14b229a2e1563cd0e2bb 100644 (file)
@@ -101,8 +101,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index a67ec91a28c3ebcdffff742122d1ee414979e912..684f40dc8a41b65d9750497f9a78023ba4e54be0 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=32
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 886cb6aa64326fa1441d70b3f5e1b9f5655c4e8b..e202924e617322f4fb3d008e44135ca967e224e0 100644 (file)
@@ -103,8 +103,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 1b2f41dbcafbb7e5020d3eab045ef7cebb494286..c348a4662a9e7caeff57aef7f8db1931849651ac 100644 (file)
@@ -102,8 +102,7 @@ CONFIG_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 12041d355b8ca1a9e47914d68211d416a405fb92..f4cb7e84cb833f398c3659c2ad7eb0263bcb1806 100644 (file)
@@ -101,8 +101,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 2518b8568c70c5538c96c9fed3b19e2d709abcac..c7ead0ec00bc229b2ea2ab278102d73926d44e30 100644 (file)
@@ -80,8 +80,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 218d49b36a0ce3e0e538539826dbbefba940dd86..7664c83c17c267308f598e27200a0ca14b487081 100644 (file)
@@ -95,8 +95,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 90492ff25232aad737899f3b883ac53d97a22c49..eac7c17eef3468bf70e0e1b505a967958b774115 100644 (file)
@@ -96,8 +96,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index dffc8cac825fb72e4e108dfdf6f10d6a7decd005..27afb6ecdf6119dd42cf1fd8f9aabf56604c787e 100644 (file)
@@ -95,8 +95,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 3cb2a522046a9aac204099641b693604da6ab266..5fe39ddb4e14e75c8c151159d00d5b9a076090c6 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
index 96181c62abfafe805cb39c61799dce5176daed15..a108b84c0074284c929bccb37d22197faf2407a6 100644 (file)
@@ -95,8 +95,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 183c59c6d8966a0c41469a178adbef50524a173e..b728a7d642504e7c486c7955e1209fa2922fd4c8 100644 (file)
@@ -103,8 +103,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_RELAY=y
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 1524d948a2ba2f952ff6d6961553054ec276bc72..8e738de5f6a59aa8176ef362fcdd5d09e9ebb813 100644 (file)
@@ -103,8 +103,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_RELAY=y
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 767c204c060311f6c32549b4ee38f38296ced643..59bf9e27d7f2d6d3de298db786b2f77e8df016c6 100644 (file)
@@ -103,8 +103,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_RELAY=y
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 55b9e4e867acede870365cee89c1f93a9b624e2d..4e8b01e73245036b4c8f196ce034a38765df5cfe 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 1be38eb057832fbf0019ff7d4bf5d307917bcb4c..20fde6374aaded20bda4a49d7851db92ffe812f8 100644 (file)
@@ -103,8 +103,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index a63009457323cb87eff5d5a3b3b74b9a7a5a540b..74f714d85936313dfd3e9746c29239553ac693db 100644 (file)
@@ -102,8 +102,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_RELAY=y
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 9f89d5c9c0be129161fca939a0c232031ae8e232..a670cee255b9d35acd5098e9edaca2a962e2a080 100644 (file)
@@ -92,8 +92,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
index b63cc38df6b1d37aadb80928266e284c32d453d9..851287e78fc3f19af8ba46e33f0c4d6217b7e304 100644 (file)
@@ -87,8 +87,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 4ab6074db3cfbeebdf7f1e7b6ec07d2334909808..b429a655b54134111411fb52cdb72064a6f0e81c 100644 (file)
@@ -102,8 +102,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index c6d2baa7aaebf3e5f8c7a7058b85de662426df6a..943371954317342109ea67a6876353c537564012 100644 (file)
@@ -83,8 +83,7 @@ CONFIG_CPUSETS=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUP_CPUACCT is not set
 # CONFIG_RESOURCE_COUNTERS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_PROC_PID_CPUSET=y
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
index d2123779512aab461de284edb05b860a9a50c89c..6be6c09eba6d0d975288ec4d65fe4014bb0346c7 100644 (file)
@@ -78,8 +78,7 @@ CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_USER_SCHED is not set
 # CONFIG_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 5094a65a44938cc7ece391efc7cbbf9257674403..2fdab660fce31f3f3b078448fe133f4d9ae646dd 100644 (file)
@@ -77,8 +77,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 81e904e9f392799854c9057677e6381f352549c0..6b708395a7c69685798bb8cc0e4e078362f8eb0e 100644 (file)
@@ -96,8 +96,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
index c5af46ef5f40a1dc074e9db224d2bedf8b972dbe..1cee889dd9ec7bf86aed3d3de2c83fcf4f20a96b 100644 (file)
@@ -91,8 +91,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
index 826a65d3f002ddb37d1f1f077888ab3b56839448..57d3ffa3026af016e7ab811a299dbe108c9b12e2 100644 (file)
@@ -82,8 +82,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 942e1193e9e4e8c053b1d3a237ae4ec74f0b5840..1c2dbf07ac35dbb38332772ec5d2629803421438 100644 (file)
@@ -101,8 +101,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index a211a79959ca867b3210f4461c64df9f486c6ff7..a60d61bee48df33557f4d4b7c1f0fdc2743e8db9 100644 (file)
@@ -73,7 +73,6 @@ CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
 # CONFIG_FAIR_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
index 76982c51a4c793d3910ae09d5545b1f6f9114766..151c8e14f3ab677acd1fd3a023cd07667c14b4b2 100644 (file)
@@ -81,8 +81,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 588a2add393fa9e713f959c367c31a215a2fb55f..8ecacf74d3e5d1909fb226c553dd547db37dc9f9 100644 (file)
@@ -97,8 +97,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 8b244003b9e1bcf7b48b2518a374ebc578f16e5d..dc50eec58e780c64949130421b5f32cfe73cc559 100644 (file)
@@ -78,8 +78,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 0cbd56fe2e1e132e19f24360b6fbcd8753303e91..b36ebb7e843e699b9527d0e3ac99abdb39174a53 100644 (file)
@@ -96,8 +96,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index c1be26151021154783b21fae5f4e0bba635b0b56..0dd5015ea81d1ac522e55988a694bbf1cb5b91fc 100644 (file)
@@ -90,8 +90,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index a04727295d46ed7f2fb40b1f5b8cb0ae661f2031..aa2654e6edeb739ced7022e2e9c7093a75bdd8c2 100644 (file)
@@ -97,8 +97,7 @@ CONFIG_RCU_FANOUT=32
 CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 7012ac0134f0d99655f618514138b257f9be28b9..f875ec21c91c7f0934dd3a68ad57e1db34e5aa0d 100644 (file)
@@ -97,8 +97,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 27c63ceeb45a633feb5fefb57c290f22d470fdd2..b1e88fe1d9fb0693de2adff45650d572d6417d52 100644 (file)
@@ -95,8 +95,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 20ba0cfff8ba35dcdd50737140ccf640b9a1034b..74a7216183e8cf645ed43a093e336f18cf4fbdce 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=64
 CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index ea8870a34482a27daf52c512687cfdfd5658f486..753bb7912e28b17e34711bc890865e12a35a070f 100644 (file)
@@ -93,8 +93,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 35b60683cde5570c314b33360113f1617e369e7a..afb4d1bb2ba98c83b6623081fac98f3ac12c723f 100644 (file)
@@ -99,8 +99,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 46f5c47e9f8512287db8d4aecc02c59aee9690da..bd3d23fb4dd3e8a70560c639e9ccb3bb25106c67 100644 (file)
@@ -103,8 +103,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index dad617e2a88cfe4161f605bb8861fafd5814cf3f..369f4e02c5dd45f7d7ace372dd240e177209b6d5 100644 (file)
@@ -93,8 +93,7 @@ CONFIG_CPUSETS=y
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUP_CPUACCT is not set
 # CONFIG_RESOURCE_COUNTERS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_PROC_PID_CPUSET=y
 CONFIG_RELAY=y
 CONFIG_NAMESPACES=y
index 8195f1650cbfe0aaef708fd68f097316aca0e632..403e82e2e83cc51ca03732b2fc8a18d08a46f13d 100644 (file)
@@ -107,8 +107,7 @@ CONFIG_CPUSETS=y
 CONFIG_PROC_PID_CPUSET=y
 # CONFIG_CGROUP_CPUACCT is not set
 # CONFIG_RESOURCE_COUNTERS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_RELAY=y
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 68c175ea427a465dbb53ace458d40cc320fc781f..12c8ee8dd12be81f9877b583a564ba21f98164aa 100644 (file)
@@ -96,8 +96,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 93f4505b5ac2a1334c1344438b6db9b40fa216f8..a18f597c6e5fa8f20fd18b4cc674783764cca71c 100644 (file)
@@ -98,8 +98,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
index 16a14589bd40ab6a331933c032d6fe72312234f9..16ae717d195885d15659df18c0b846cb489f3b85 100644 (file)
@@ -92,8 +92,7 @@ CONFIG_CPUSETS=y
 # CONFIG_GROUP_SCHED is not set
 CONFIG_CGROUP_CPUACCT=y
 # CONFIG_RESOURCE_COUNTERS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_PROC_PID_CPUSET=y
 CONFIG_RELAY=y
 CONFIG_NAMESPACES=y
index b1625801526e8fbc901775b53a9a763aed74d3ca..01be0e207f40173f8c103f06b4bd45ce19ffad12 100644 (file)
@@ -95,8 +95,7 @@ CONFIG_RCU_FANOUT=32
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
index c386828c639a37d8a8083fdfcbc26167d8f43c34..ee054f8118be65ba14344bb80c6163ad7433a969 100644 (file)
@@ -102,8 +102,7 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_RELAY=y
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
index 725634fc18c653d2a868262a84d450a7d3d3edab..4b509411ad8afcf52cf1ea5beca482b9fc282d22 100644 (file)
@@ -42,7 +42,7 @@ extern struct ppc64_caches ppc64_caches;
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
 #if !defined(__ASSEMBLY__)
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 #endif
 
 #endif /* __KERNEL__ */
index e3cba4e1eb347368307c83906c3845a017bc8aee..b0b21134f61a8f6fb30305b46d4f2cd07aae132f 100644 (file)
@@ -70,6 +70,7 @@ struct pt_regs;
 extern int machine_check_generic(struct pt_regs *regs);
 extern int machine_check_4xx(struct pt_regs *regs);
 extern int machine_check_440A(struct pt_regs *regs);
+extern int machine_check_e500mc(struct pt_regs *regs);
 extern int machine_check_e500(struct pt_regs *regs);
 extern int machine_check_e200(struct pt_regs *regs);
 extern int machine_check_47x(struct pt_regs *regs);
index e054baef184599f2c13703ed688afb1d8fe0d3f6..ecba37a91749a1e869ed26afff90563b85813cb6 100644 (file)
@@ -358,7 +358,6 @@ extern void exc_lvl_ctx_init(void);
 #define exc_lvl_ctx_init()
 #endif
 
-#ifdef CONFIG_IRQSTACKS
 /*
  * Per-cpu stacks for handling hard and soft interrupts.
  */
@@ -369,11 +368,6 @@ extern void irq_ctx_init(void);
 extern void call_do_softirq(struct thread_info *tp);
 extern int call_handle_irq(int irq, void *p1,
                           struct thread_info *tp, void *func);
-#else
-#define irq_ctx_init()
-
-#endif /* CONFIG_IRQSTACKS */
-
 extern void do_IRQ(struct pt_regs *regs);
 
 #endif /* _ASM_IRQ_H */
index 5ebfe5d3c61ff23c8dd411f8ed8816d0e5286c01..6857af58b02eef9ddc9f2a91d42d28259a5a4b6b 100644 (file)
@@ -3,8 +3,17 @@
 
 #include <asm/page.h>
 
-/* Kdump kernel runs at 32 MB, change at your peril. */
+/*
+ * If CONFIG_RELOCATABLE is enabled we can place the kdump kernel anywhere.
+ * To keep enough space in the RMO for the first stage kernel on 64bit, we
+ * place it at 64MB. If CONFIG_RELOCATABLE is not enabled we must place
+ * the second stage at 32MB.
+ */
+#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_PPC64)
+#define KDUMP_KERNELBASE       0x4000000
+#else
 #define KDUMP_KERNELBASE       0x2000000
+#endif
 
 /* How many bytes to reserve at zero for kdump. The reserve limit should
  * be greater or equal to the trampoline's end address.
index a6ca6da1430bd60506af9b5babc62df147c8c9f7..2a9cd74a841e3e234b6d1a4bb6beb8e5cd1b207b 100644 (file)
@@ -2,6 +2,18 @@
 #define _ASM_POWERPC_KEXEC_H
 #ifdef __KERNEL__
 
+#ifdef CONFIG_FSL_BOOKE
+
+/*
+ * On FSL-BookE we setup a 1:1 mapping which covers the first 2GiB of memory
+ * and therefore we can only deal with memory within this range
+ */
+#define KEXEC_SOURCE_MEMORY_LIMIT      (2 * 1024 * 1024 * 1024UL)
+#define KEXEC_DESTINATION_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
+#define KEXEC_CONTROL_MEMORY_LIMIT     (2 * 1024 * 1024 * 1024UL)
+
+#else
+
 /*
  * Maximum page that is mapped directly into kernel memory.
  * XXX: Since we copy virt we can use any page we allocate
@@ -21,6 +33,7 @@
 /* TASK_SIZE, probably left over from use_mm ?? */
 #define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
 #endif
+#endif
 
 #define KEXEC_CONTROL_PAGE_SIZE 4096
 
index 19a661b4cb98205f6304c3c449062e6ca20e3c94..675e159b5ef42decbf2617870963547f07016870 100644 (file)
@@ -123,10 +123,6 @@ static inline struct pci_dev *macio_get_pci_dev(struct macio_dev *mdev)
  */
 struct macio_driver
 {
-       char                    *name;
-       struct of_device_id     *match_table;
-       struct module           *owner;
-
        int     (*probe)(struct macio_dev* dev, const struct of_device_id *match);
        int     (*remove)(struct macio_dev* dev);
 
index bfc4e027e2adf75640e99cd4c35555fc2834f3d8..358ff14ea25ed2d917f442576dba3ac841a1f9b5 100644 (file)
@@ -162,14 +162,6 @@ do {                                               \
 
 #endif /* !CONFIG_HUGETLB_PAGE */
 
-#ifdef MODULE
-#define __page_aligned __attribute__((__aligned__(PAGE_SIZE)))
-#else
-#define __page_aligned \
-       __attribute__((__aligned__(PAGE_SIZE), \
-               __section__(".data.page_aligned")))
-#endif
-
 #define VM_DATA_DEFAULT_FLAGS \
        (test_thread_flag(TIF_32BIT) ? \
         VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64)
index 5304a37ba425c42b17a0384616f00b977d7f0b3a..2360317179a9163412449bcecb62efd976acd20a 100644 (file)
@@ -4,6 +4,12 @@
  * are not true Book E PowerPCs, they borrowed a number of features
  * before Book E was finalized, and are included here as well.  Unfortunatly,
  * they sometimes used different locations than true Book E CPUs did.
+ *
+ * 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.
+ *
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
  */
 #ifdef __KERNEL__
 #ifndef __ASM_POWERPC_REG_BOOKE_H__
@@ -88,6 +94,7 @@
 #define SPRN_IVOR35    0x213   /* Interrupt Vector Offset Register 35 */
 #define SPRN_IVOR36    0x214   /* Interrupt Vector Offset Register 36 */
 #define SPRN_IVOR37    0x215   /* Interrupt Vector Offset Register 37 */
+#define SPRN_MCARU     0x239   /* Machine Check Address Register Upper */
 #define SPRN_MCSRR0    0x23A   /* Machine Check Save and Restore Register 0 */
 #define SPRN_MCSRR1    0x23B   /* Machine Check Save and Restore Register 1 */
 #define SPRN_MCSR      0x23C   /* Machine Check Status Register */
 #define PPC47x_MCSR_IPR        0x00400000 /* Imprecise Machine Check Exception */
 
 #ifdef CONFIG_E500
+/* All e500 */
 #define MCSR_MCP       0x80000000UL /* Machine Check Input Pin */
 #define MCSR_ICPERR    0x40000000UL /* I-Cache Parity Error */
+
+/* e500v1/v2 */
 #define MCSR_DCP_PERR  0x20000000UL /* D-Cache Push Parity Error */
 #define MCSR_DCPERR    0x10000000UL /* D-Cache Parity Error */
 #define MCSR_BUS_IAERR         0x00000080UL /* Instruction Address Error */
 #define MCSR_BUS_IPERR         0x00000002UL /* Instruction parity Error */
 #define MCSR_BUS_RPERR         0x00000001UL /* Read parity Error */
 
-/* e500 parts may set unused bits in MCSR; mask these off */
-#define MCSR_MASK      (MCSR_MCP | MCSR_ICPERR | MCSR_DCP_PERR | \
-                       MCSR_DCPERR | MCSR_BUS_IAERR | MCSR_BUS_RAERR | \
-                       MCSR_BUS_WAERR | MCSR_BUS_IBERR | MCSR_BUS_RBERR | \
-                       MCSR_BUS_WBERR | MCSR_BUS_IPERR | MCSR_BUS_RPERR)
+/* e500mc */
+#define MCSR_DCPERR_MC 0x20000000UL /* D-Cache Parity Error */
+#define MCSR_L2MMU_MHIT        0x04000000UL /* Hit on multiple TLB entries */
+#define MCSR_NMI       0x00100000UL /* Non-Maskable Interrupt */
+#define MCSR_MAV       0x00080000UL /* MCAR address valid */
+#define MCSR_MEA       0x00040000UL /* MCAR is effective address */
+#define MCSR_IF                0x00010000UL /* Instruction Fetch */
+#define MCSR_LD                0x00008000UL /* Load */
+#define MCSR_ST                0x00004000UL /* Store */
+#define MCSR_LDG       0x00002000UL /* Guarded Load */
+#define MCSR_TLBSYNC   0x00000002UL /* Multiple tlbsyncs detected */
+#define MCSR_BSL2_ERR  0x00000001UL /* Backside L2 cache error */
 #endif
+
 #ifdef CONFIG_E200
 #define MCSR_MCP       0x80000000UL /* Machine Check Input Pin */
 #define MCSR_CP_PERR   0x20000000UL /* Cache Push Parity Error */
 #define MCSR_BUS_DRERR         0x00000008UL /* Read Bus Error on data load */
 #define MCSR_BUS_WRERR         0x00000004UL /* Write Bus Error on buffered
                                        store or cache line push */
-
-/* e200 parts may set unused bits in MCSR; mask these off */
-#define MCSR_MASK      (MCSR_MCP | MCSR_CP_PERR | MCSR_CPERR | \
-                       MCSR_EXCP_ERR | MCSR_BUS_IRERR | MCSR_BUS_DRERR | \
-                       MCSR_BUS_WRERR)
 #endif
 
 /* Bit definitions for the DBSR. */
index 877326320e74197802c4eeb4855d60f66344c6ff..58d0572de6f9b13f4b74035d323cefc83b8dce04 100644 (file)
@@ -57,8 +57,12 @@ obj-$(CONFIG_CRASH_DUMP)     += crash_dump.o
 obj-$(CONFIG_E500)             += idle_e500.o
 obj-$(CONFIG_6xx)              += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
 obj-$(CONFIG_TAU)              += tau_6xx.o
-obj-$(CONFIG_HIBERNATION)      += swsusp.o suspend.o \
-                                  swsusp_$(CONFIG_WORD_SIZE).o
+obj-$(CONFIG_HIBERNATION)      += swsusp.o suspend.o
+ifeq ($(CONFIG_FSL_BOOKE),y)
+obj-$(CONFIG_HIBERNATION)      += swsusp_booke.o
+else
+obj-$(CONFIG_HIBERNATION)      += swsusp_$(CONFIG_WORD_SIZE).o
+endif
 obj64-$(CONFIG_HIBERNATION)    += swsusp_asm64.o
 obj-$(CONFIG_MODULES)          += module.o module_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_44x)              += cpu_setup_44x.o
index 9556be903e9638e8fcadc898e81328f0772c7c3d..87aa0f3c60475aeaa71474ded7d46c2f34078ffb 100644 (file)
@@ -1840,7 +1840,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_cpu_type      = "ppc/e500mc",
                .oprofile_type          = PPC_OPROFILE_FSL_EMB,
                .cpu_setup              = __setup_cpu_e500mc,
-               .machine_check          = machine_check_e500,
+               .machine_check          = machine_check_e500mc,
                .platform               = "ppce500mc",
        },
        {       /* default match */
index 8c066d6a8e4b4ee015bc8ccf93bf5fc321267bbe..b46f2e09bd81df4bea175401fe4f70fbf45bfb35 100644 (file)
@@ -163,6 +163,7 @@ static void crash_kexec_prepare_cpus(int cpu)
 }
 
 /* wait for all the CPUs to hit real mode but timeout if they don't come in */
+#ifdef CONFIG_PPC_STD_MMU_64
 static void crash_kexec_wait_realmode(int cpu)
 {
        unsigned int msecs;
@@ -187,6 +188,7 @@ static void crash_kexec_wait_realmode(int cpu)
        }
        mb();
 }
+#endif
 
 /*
  * This function will be called by secondary cpus or by kexec cpu
@@ -445,7 +447,9 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
        crash_kexec_prepare_cpus(crashing_cpu);
        cpu_set(crashing_cpu, cpus_in_crash);
        crash_kexec_stop_spus();
+#ifdef CONFIG_PPC_STD_MMU_64
        crash_kexec_wait_realmode(crashing_cpu);
+#endif
        if (ppc_md.kexec_cpu_down)
                ppc_md.kexec_cpu_down(1, 0);
 }
diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
new file mode 100644 (file)
index 0000000..beb4d78
--- /dev/null
@@ -0,0 +1,237 @@
+
+/* 1. Find the index of the entry we're executing in */
+       bl      invstr                          /* Find our address */
+invstr:        mflr    r6                              /* Make it accessible */
+       mfmsr   r7
+       rlwinm  r4,r7,27,31,31                  /* extract MSR[IS] */
+       mfspr   r7, SPRN_PID0
+       slwi    r7,r7,16
+       or      r7,r7,r4
+       mtspr   SPRN_MAS6,r7
+       tlbsx   0,r6                            /* search MSR[IS], SPID=PID0 */
+       mfspr   r7,SPRN_MAS1
+       andis.  r7,r7,MAS1_VALID@h
+       bne     match_TLB
+
+       mfspr   r7,SPRN_MMUCFG
+       rlwinm  r7,r7,21,28,31                  /* extract MMUCFG[NPIDS] */
+       cmpwi   r7,3
+       bne     match_TLB                       /* skip if NPIDS != 3 */
+
+       mfspr   r7,SPRN_PID1
+       slwi    r7,r7,16
+       or      r7,r7,r4
+       mtspr   SPRN_MAS6,r7
+       tlbsx   0,r6                            /* search MSR[IS], SPID=PID1 */
+       mfspr   r7,SPRN_MAS1
+       andis.  r7,r7,MAS1_VALID@h
+       bne     match_TLB
+       mfspr   r7, SPRN_PID2
+       slwi    r7,r7,16
+       or      r7,r7,r4
+       mtspr   SPRN_MAS6,r7
+       tlbsx   0,r6                            /* Fall through, we had to match */
+
+match_TLB:
+       mfspr   r7,SPRN_MAS0
+       rlwinm  r3,r7,16,20,31                  /* Extract MAS0(Entry) */
+
+       mfspr   r7,SPRN_MAS1                    /* Insure IPROT set */
+       oris    r7,r7,MAS1_IPROT@h
+       mtspr   SPRN_MAS1,r7
+       tlbwe
+
+/* 2. Invalidate all entries except the entry we're executing in */
+       mfspr   r9,SPRN_TLB1CFG
+       andi.   r9,r9,0xfff
+       li      r6,0                            /* Set Entry counter to 0 */
+1:     lis     r7,0x1000                       /* Set MAS0(TLBSEL) = 1 */
+       rlwimi  r7,r6,16,4,15                   /* Setup MAS0 = TLBSEL | ESEL(r6) */
+       mtspr   SPRN_MAS0,r7
+       tlbre
+       mfspr   r7,SPRN_MAS1
+       rlwinm  r7,r7,0,2,31                    /* Clear MAS1 Valid and IPROT */
+       cmpw    r3,r6
+       beq     skpinv                          /* Dont update the current execution TLB */
+       mtspr   SPRN_MAS1,r7
+       tlbwe
+       isync
+skpinv:        addi    r6,r6,1                         /* Increment */
+       cmpw    r6,r9                           /* Are we done? */
+       bne     1b                              /* If not, repeat */
+
+       /* Invalidate TLB0 */
+       li      r6,0x04
+       tlbivax 0,r6
+       TLBSYNC
+       /* Invalidate TLB1 */
+       li      r6,0x0c
+       tlbivax 0,r6
+       TLBSYNC
+
+/* 3. Setup a temp mapping and jump to it */
+       andi.   r5, r3, 0x1     /* Find an entry not used and is non-zero */
+       addi    r5, r5, 0x1
+       lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
+       rlwimi  r7,r3,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r3) */
+       mtspr   SPRN_MAS0,r7
+       tlbre
+
+       /* grab and fixup the RPN */
+       mfspr   r6,SPRN_MAS1    /* extract MAS1[SIZE] */
+       rlwinm  r6,r6,25,27,31
+       li      r8,-1
+       addi    r6,r6,10
+       slw     r6,r8,r6        /* convert to mask */
+
+       bl      1f              /* Find our address */
+1:     mflr    r7
+
+       mfspr   r8,SPRN_MAS3
+#ifdef CONFIG_PHYS_64BIT
+       mfspr   r23,SPRN_MAS7
+#endif
+       and     r8,r6,r8
+       subfic  r9,r6,-4096
+       and     r9,r9,r7
+
+       or      r25,r8,r9
+       ori     r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
+
+       /* Just modify the entry ID and EPN for the temp mapping */
+       lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
+       rlwimi  r7,r5,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r5) */
+       mtspr   SPRN_MAS0,r7
+       xori    r6,r4,1         /* Setup TMP mapping in the other Address space */
+       slwi    r6,r6,12
+       oris    r6,r6,(MAS1_VALID|MAS1_IPROT)@h
+       ori     r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
+       mtspr   SPRN_MAS1,r6
+       mfspr   r6,SPRN_MAS2
+       li      r7,0            /* temp EPN = 0 */
+       rlwimi  r7,r6,0,20,31
+       mtspr   SPRN_MAS2,r7
+       mtspr   SPRN_MAS3,r8
+       tlbwe
+
+       xori    r6,r4,1
+       slwi    r6,r6,5         /* setup new context with other address space */
+       bl      1f              /* Find our address */
+1:     mflr    r9
+       rlwimi  r7,r9,0,20,31
+       addi    r7,r7,(2f - 1b)
+       mtspr   SPRN_SRR0,r7
+       mtspr   SPRN_SRR1,r6
+       rfi
+2:
+/* 4. Clear out PIDs & Search info */
+       li      r6,0
+       mtspr   SPRN_MAS6,r6
+       mtspr   SPRN_PID0,r6
+
+       mfspr   r7,SPRN_MMUCFG
+       rlwinm  r7,r7,21,28,31                  /* extract MMUCFG[NPIDS] */
+       cmpwi   r7,3
+       bne     2f                              /* skip if NPIDS != 3 */
+
+       mtspr   SPRN_PID1,r6
+       mtspr   SPRN_PID2,r6
+
+/* 5. Invalidate mapping we started in */
+2:
+       lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
+       rlwimi  r7,r3,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r3) */
+       mtspr   SPRN_MAS0,r7
+       tlbre
+       mfspr   r6,SPRN_MAS1
+       rlwinm  r6,r6,0,2,0     /* clear IPROT */
+       mtspr   SPRN_MAS1,r6
+       tlbwe
+       /* Invalidate TLB1 */
+       li      r9,0x0c
+       tlbivax 0,r9
+       TLBSYNC
+
+/* The mapping only needs to be cache-coherent on SMP */
+#ifdef CONFIG_SMP
+#define M_IF_SMP       MAS2_M
+#else
+#define M_IF_SMP       0
+#endif
+
+#if defined(ENTRY_MAPPING_BOOT_SETUP)
+
+/* 6. Setup KERNELBASE mapping in TLB1[0] */
+       lis     r6,0x1000               /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
+       mtspr   SPRN_MAS0,r6
+       lis     r6,(MAS1_VALID|MAS1_IPROT)@h
+       ori     r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
+       mtspr   SPRN_MAS1,r6
+       lis     r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
+       ori     r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
+       mtspr   SPRN_MAS2,r6
+       mtspr   SPRN_MAS3,r8
+       tlbwe
+
+/* 7. Jump to KERNELBASE mapping */
+       lis     r6,(KERNELBASE & ~0xfff)@h
+       ori     r6,r6,(KERNELBASE & ~0xfff)@l
+
+#elif defined(ENTRY_MAPPING_KEXEC_SETUP)
+/*
+ * 6. Setup a 1:1 mapping in TLB1. Esel 0 is unsued, 1 or 2 contains the tmp
+ * mapping so we start at 3. We setup 8 mappings, each 256MiB in size. This
+ * will cover the first 2GiB of memory.
+ */
+
+       lis r10, (MAS1_VALID|MAS1_IPROT)@h
+       ori r10,r10, (MAS1_TSIZE(BOOK3E_PAGESZ_256M))@l
+       li  r11, 0
+       li  r0, 8
+       mtctr   r0
+
+next_tlb_setup:
+       addi    r0, r11, 3
+       rlwinm  r0, r0, 16, 4, 15  // Compute esel
+       rlwinm  r9, r11, 28, 0, 3   // Compute [ER]PN
+       oris    r0, r0, (MAS0_TLBSEL(1))@h
+       mtspr   SPRN_MAS0,r0
+       mtspr   SPRN_MAS1,r10
+       mtspr   SPRN_MAS2,r9
+       ori r9, r9, (MAS3_SX|MAS3_SW|MAS3_SR)
+       mtspr   SPRN_MAS3,r9
+       tlbwe
+       addi    r11, r11, 1
+       bdnz+   next_tlb_setup
+
+/* 7. Jump to our 1:1 mapping */
+       li      r6, 0
+
+#else
+       #error You need to specify the mapping or not use this at all.
+#endif
+
+       lis     r7,MSR_KERNEL@h
+       ori     r7,r7,MSR_KERNEL@l
+       bl      1f                      /* Find our address */
+1:     mflr    r9
+       rlwimi  r6,r9,0,20,31
+       addi    r6,r6,(2f - 1b)
+       add     r6, r6, r25
+       mtspr   SPRN_SRR0,r6
+       mtspr   SPRN_SRR1,r7
+       rfi                             /* start execution out of TLB1[0] entry */
+
+/* 8. Clear out the temp mapping */
+2:     lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
+       rlwimi  r7,r5,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r5) */
+       mtspr   SPRN_MAS0,r7
+       tlbre
+       mfspr   r8,SPRN_MAS1
+       rlwinm  r8,r8,0,2,0     /* clear IPROT */
+       mtspr   SPRN_MAS1,r8
+       tlbwe
+       /* Invalidate TLB1 */
+       li      r9,0x0c
+       tlbivax 0,r9
+       TLBSYNC
index edd4a57fd29e154b9dc90fe1aea1cae29fb2513b..4faeba247854c038078ef4362836d50b37f4f44a 100644 (file)
@@ -94,204 +94,10 @@ _ENTRY(_start);
  */
 
 _ENTRY(__early_start)
-/* 1. Find the index of the entry we're executing in */
-       bl      invstr                          /* Find our address */
-invstr:        mflr    r6                              /* Make it accessible */
-       mfmsr   r7
-       rlwinm  r4,r7,27,31,31                  /* extract MSR[IS] */
-       mfspr   r7, SPRN_PID0
-       slwi    r7,r7,16
-       or      r7,r7,r4
-       mtspr   SPRN_MAS6,r7
-       tlbsx   0,r6                            /* search MSR[IS], SPID=PID0 */
-       mfspr   r7,SPRN_MAS1
-       andis.  r7,r7,MAS1_VALID@h
-       bne     match_TLB
-
-       mfspr   r7,SPRN_MMUCFG
-       rlwinm  r7,r7,21,28,31                  /* extract MMUCFG[NPIDS] */
-       cmpwi   r7,3
-       bne     match_TLB                       /* skip if NPIDS != 3 */
-
-       mfspr   r7,SPRN_PID1
-       slwi    r7,r7,16
-       or      r7,r7,r4
-       mtspr   SPRN_MAS6,r7
-       tlbsx   0,r6                            /* search MSR[IS], SPID=PID1 */
-       mfspr   r7,SPRN_MAS1
-       andis.  r7,r7,MAS1_VALID@h
-       bne     match_TLB
-       mfspr   r7, SPRN_PID2
-       slwi    r7,r7,16
-       or      r7,r7,r4
-       mtspr   SPRN_MAS6,r7
-       tlbsx   0,r6                            /* Fall through, we had to match */
-
-match_TLB:
-       mfspr   r7,SPRN_MAS0
-       rlwinm  r3,r7,16,20,31                  /* Extract MAS0(Entry) */
-
-       mfspr   r7,SPRN_MAS1                    /* Insure IPROT set */
-       oris    r7,r7,MAS1_IPROT@h
-       mtspr   SPRN_MAS1,r7
-       tlbwe
-
-/* 2. Invalidate all entries except the entry we're executing in */
-       mfspr   r9,SPRN_TLB1CFG
-       andi.   r9,r9,0xfff
-       li      r6,0                            /* Set Entry counter to 0 */
-1:     lis     r7,0x1000                       /* Set MAS0(TLBSEL) = 1 */
-       rlwimi  r7,r6,16,4,15                   /* Setup MAS0 = TLBSEL | ESEL(r6) */
-       mtspr   SPRN_MAS0,r7
-       tlbre
-       mfspr   r7,SPRN_MAS1
-       rlwinm  r7,r7,0,2,31                    /* Clear MAS1 Valid and IPROT */
-       cmpw    r3,r6
-       beq     skpinv                          /* Dont update the current execution TLB */
-       mtspr   SPRN_MAS1,r7
-       tlbwe
-       isync
-skpinv:        addi    r6,r6,1                         /* Increment */
-       cmpw    r6,r9                           /* Are we done? */
-       bne     1b                              /* If not, repeat */
-
-       /* Invalidate TLB0 */
-       li      r6,0x04
-       tlbivax 0,r6
-       TLBSYNC
-       /* Invalidate TLB1 */
-       li      r6,0x0c
-       tlbivax 0,r6
-       TLBSYNC
-
-/* 3. Setup a temp mapping and jump to it */
-       andi.   r5, r3, 0x1     /* Find an entry not used and is non-zero */
-       addi    r5, r5, 0x1
-       lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
-       rlwimi  r7,r3,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r3) */
-       mtspr   SPRN_MAS0,r7
-       tlbre
-
-       /* grab and fixup the RPN */
-       mfspr   r6,SPRN_MAS1    /* extract MAS1[SIZE] */
-       rlwinm  r6,r6,25,27,31
-       li      r8,-1
-       addi    r6,r6,10
-       slw     r6,r8,r6        /* convert to mask */
-
-       bl      1f              /* Find our address */
-1:     mflr    r7
-
-       mfspr   r8,SPRN_MAS3
-#ifdef CONFIG_PHYS_64BIT
-       mfspr   r23,SPRN_MAS7
-#endif
-       and     r8,r6,r8
-       subfic  r9,r6,-4096
-       and     r9,r9,r7
-
-       or      r25,r8,r9
-       ori     r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
-
-       /* Just modify the entry ID and EPN for the temp mapping */
-       lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
-       rlwimi  r7,r5,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r5) */
-       mtspr   SPRN_MAS0,r7
-       xori    r6,r4,1         /* Setup TMP mapping in the other Address space */
-       slwi    r6,r6,12
-       oris    r6,r6,(MAS1_VALID|MAS1_IPROT)@h
-       ori     r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
-       mtspr   SPRN_MAS1,r6
-       mfspr   r6,SPRN_MAS2
-       li      r7,0            /* temp EPN = 0 */
-       rlwimi  r7,r6,0,20,31
-       mtspr   SPRN_MAS2,r7
-       mtspr   SPRN_MAS3,r8
-       tlbwe
-
-       xori    r6,r4,1
-       slwi    r6,r6,5         /* setup new context with other address space */
-       bl      1f              /* Find our address */
-1:     mflr    r9
-       rlwimi  r7,r9,0,20,31
-       addi    r7,r7,(2f - 1b)
-       mtspr   SPRN_SRR0,r7
-       mtspr   SPRN_SRR1,r6
-       rfi
-2:
-/* 4. Clear out PIDs & Search info */
-       li      r6,0
-       mtspr   SPRN_MAS6,r6
-       mtspr   SPRN_PID0,r6
-
-       mfspr   r7,SPRN_MMUCFG
-       rlwinm  r7,r7,21,28,31                  /* extract MMUCFG[NPIDS] */
-       cmpwi   r7,3
-       bne     2f                              /* skip if NPIDS != 3 */
 
-       mtspr   SPRN_PID1,r6
-       mtspr   SPRN_PID2,r6
-
-/* 5. Invalidate mapping we started in */
-2:
-       lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
-       rlwimi  r7,r3,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r3) */
-       mtspr   SPRN_MAS0,r7
-       tlbre
-       mfspr   r6,SPRN_MAS1
-       rlwinm  r6,r6,0,2,0     /* clear IPROT */
-       mtspr   SPRN_MAS1,r6
-       tlbwe
-       /* Invalidate TLB1 */
-       li      r9,0x0c
-       tlbivax 0,r9
-       TLBSYNC
-
-/* The mapping only needs to be cache-coherent on SMP */
-#ifdef CONFIG_SMP
-#define M_IF_SMP       MAS2_M
-#else
-#define M_IF_SMP       0
-#endif
-
-/* 6. Setup KERNELBASE mapping in TLB1[0] */
-       lis     r6,0x1000               /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
-       mtspr   SPRN_MAS0,r6
-       lis     r6,(MAS1_VALID|MAS1_IPROT)@h
-       ori     r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
-       mtspr   SPRN_MAS1,r6
-       lis     r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
-       ori     r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
-       mtspr   SPRN_MAS2,r6
-       mtspr   SPRN_MAS3,r8
-       tlbwe
-
-/* 7. Jump to KERNELBASE mapping */
-       lis     r6,(KERNELBASE & ~0xfff)@h
-       ori     r6,r6,(KERNELBASE & ~0xfff)@l
-       lis     r7,MSR_KERNEL@h
-       ori     r7,r7,MSR_KERNEL@l
-       bl      1f                      /* Find our address */
-1:     mflr    r9
-       rlwimi  r6,r9,0,20,31
-       addi    r6,r6,(2f - 1b)
-       mtspr   SPRN_SRR0,r6
-       mtspr   SPRN_SRR1,r7
-       rfi                             /* start execution out of TLB1[0] entry */
-
-/* 8. Clear out the temp mapping */
-2:     lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
-       rlwimi  r7,r5,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r5) */
-       mtspr   SPRN_MAS0,r7
-       tlbre
-       mfspr   r8,SPRN_MAS1
-       rlwinm  r8,r8,0,2,0     /* clear IPROT */
-       mtspr   SPRN_MAS1,r8
-       tlbwe
-       /* Invalidate TLB1 */
-       li      r9,0x0c
-       tlbivax 0,r9
-       TLBSYNC
+#define ENTRY_MAPPING_BOOT_SETUP
+#include "fsl_booke_entry_mapping.S"
+#undef ENTRY_MAPPING_BOOT_SETUP
 
        /* Establish the interrupt vector offsets */
        SET_IVOR(0,  CriticalInput);
index 30817d9b20cb59ecb12741edee7d0dacf5366dc3..3333bbdd23efaffce914c4b64c24ac766aba1fc3 100644 (file)
@@ -317,7 +317,6 @@ void fixup_irqs(const struct cpumask *map)
 }
 #endif
 
-#ifdef CONFIG_IRQSTACKS
 static inline void handle_one_irq(unsigned int irq)
 {
        struct thread_info *curtp, *irqtp;
@@ -358,12 +357,6 @@ static inline void handle_one_irq(unsigned int irq)
        if (irqtp->flags)
                set_bits(irqtp->flags, &curtp->flags);
 }
-#else
-static inline void handle_one_irq(unsigned int irq)
-{
-       generic_handle_irq(irq);
-}
-#endif
 
 static inline void check_stack_overflow(void)
 {
@@ -455,7 +448,6 @@ void exc_lvl_ctx_init(void)
 }
 #endif
 
-#ifdef CONFIG_IRQSTACKS
 struct thread_info *softirq_ctx[NR_CPUS] __read_mostly;
 struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly;
 
@@ -492,10 +484,6 @@ static inline void do_softirq_onstack(void)
        irqtp->task = NULL;
 }
 
-#else
-#define do_softirq_onstack()   __do_softirq()
-#endif /* CONFIG_IRQSTACKS */
-
 void do_softirq(void)
 {
        unsigned long flags;
index c533525ca56a67840aeb6a24001506a90175ca3d..bc47352deb1fec8f76fc1ac9f094c941cc2a9e4f 100644 (file)
@@ -378,17 +378,6 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
  * single-stepped a copy of the instruction.  The address of this
  * copy is p->ainsn.insn.
  */
-static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
-{
-       int ret;
-       unsigned int insn = *p->ainsn.insn;
-
-       regs->nip = (unsigned long)p->addr;
-       ret = emulate_step(regs, insn);
-       if (ret == 0)
-               regs->nip = (unsigned long)p->addr + 4;
-}
-
 static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *cur = kprobe_running();
@@ -406,7 +395,8 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
                cur->post_handler(cur, regs, 0);
        }
 
-       resume_execution(cur, regs);
+       /* Adjust nip to after the single-stepped instruction */
+       regs->nip = (unsigned long)cur->addr + 4;
        regs->msr |= kcb->kprobe_saved_msr;
 
        /*Restore back the original saved kprobes variables and continue. */
index 26f9900f773cb2e17634538f1674882c0cd7447b..ed31a29c4ff772cb22bbf038603b4bbd83731888 100644 (file)
@@ -182,28 +182,12 @@ static void kexec_prepare_cpus_wait(int wait_state)
 
        my_cpu = get_cpu();
        /* Make sure each CPU has atleast made it to the state we need */
-       for (i=0; i < NR_CPUS; i++) {
+       for_each_online_cpu(i) {
                if (i == my_cpu)
                        continue;
 
                while (paca[i].kexec_state < wait_state) {
                        barrier();
-                       if (!cpu_possible(i)) {
-                               printk("kexec: cpu %d hw_cpu_id %d is not"
-                                               " possible, ignoring\n",
-                                               i, paca[i].hw_cpu_id);
-                               break;
-                       }
-                       if (!cpu_online(i)) {
-                               /* Fixme: this can be spinning in
-                                * pSeries_secondary_wait with a paca
-                                * waiting for it to go online.
-                                */
-                               printk("kexec: cpu %d hw_cpu_id %d is not"
-                                               " online, ignoring\n",
-                                               i, paca[i].hw_cpu_id);
-                               break;
-                       }
                        if (i != notified) {
                                printk( "kexec: waiting for cpu %d (physical"
                                                " %d) to enter %i state\n",
index 8043d1b73cf0cbe98186b3e38aadbf908b283d3e..6bbd7a604d243c9f8f9f906d683a9a20df2f9a43 100644 (file)
@@ -33,7 +33,6 @@
 
        .text
 
-#ifdef CONFIG_IRQSTACKS
 _GLOBAL(call_do_softirq)
        mflr    r0
        stw     r0,4(r1)
@@ -56,7 +55,6 @@ _GLOBAL(call_handle_irq)
        lwz     r0,4(r1)
        mtlr    r0
        blr
-#endif /* CONFIG_IRQSTACKS */
 
 /*
  * This returns the high 64 bits of the product of two 64-bit numbers.
@@ -711,6 +709,22 @@ relocate_new_kernel:
        /* r4 = reboot_code_buffer */
        /* r5 = start_address      */
 
+#ifdef CONFIG_FSL_BOOKE
+
+       mr      r29, r3
+       mr      r30, r4
+       mr      r31, r5
+
+#define ENTRY_MAPPING_KEXEC_SETUP
+#include "fsl_booke_entry_mapping.S"
+#undef ENTRY_MAPPING_KEXEC_SETUP
+
+       mr      r3, r29
+       mr      r4, r30
+       mr      r5, r31
+
+       li      r0, 0
+#else
        li      r0, 0
 
        /*
@@ -727,6 +741,7 @@ relocate_new_kernel:
        rfi
 
 1:
+#endif
        /* from this point address translation is turned off */
        /* and interrupts are disabled */
 
index a2b18dffa03e4266a402aa58f8118e45fdffa74f..e5144906a56da692d1151db9e55db00ebdc73b2a 100644 (file)
@@ -28,7 +28,6 @@
 
        .text
 
-#ifdef CONFIG_IRQSTACKS
 _GLOBAL(call_do_softirq)
        mflr    r0
        std     r0,16(r1)
@@ -52,7 +51,6 @@ _GLOBAL(call_handle_irq)
        ld      r0,16(r1)
        mtlr    r0
        blr
-#endif /* CONFIG_IRQSTACKS */
 
        .section        ".toc","aw"
 PPC64_CACHES:
index 6646005dffb102b8b57172442aa8a71c5ed85a82..5b38f6ae2b299695139c25a21cff0b73f8857808 100644 (file)
@@ -1309,6 +1309,7 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
                printk(KERN_WARNING "PCI: Cannot allocate resource region "
                       "%d of PCI bridge %d, will remap\n", i, bus->number);
 clear_resource:
+               res->start = res->end = 0;
                res->flags = 0;
        }
 
index bc9f39d2598bcf7df0e26c95eaa2f5054e005ca9..3b4dcc82a4c1f43ab1f26a29506591e0d4aa4369 100644 (file)
@@ -101,7 +101,7 @@ EXPORT_SYMBOL(pci_dram_offset);
 EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(kernel_thread);
 
-#ifndef CONFIG_BOOKE
+#ifdef CONFIG_PPC_FPU
 EXPORT_SYMBOL_GPL(cvt_df);
 EXPORT_SYMBOL_GPL(cvt_fd);
 #endif
index 9d255b4f0a0ec72678bbad3787d596a8c6be13d1..773424df828a393d9a2860ded0b380978cfdd9cc 100644 (file)
@@ -1005,7 +1005,6 @@ out:
        return error;
 }
 
-#ifdef CONFIG_IRQSTACKS
 static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
                                  unsigned long nbytes)
 {
@@ -1030,10 +1029,6 @@ static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
        return 0;
 }
 
-#else
-#define valid_irq_stack(sp, p, nb)     0
-#endif /* CONFIG_IRQSTACKS */
-
 int validate_sp(unsigned long sp, struct task_struct *p,
                       unsigned long nbytes)
 {
index bfc2abafac44ab2f8d510384e4eb9a98a9b8cb17..67a84d8f118d665ff78d965752ab08dc3152760e 100644 (file)
@@ -94,12 +94,8 @@ struct flash_block_list {
        struct flash_block_list *next;
        struct flash_block blocks[FLASH_BLOCKS_PER_NODE];
 };
-struct flash_block_list_header { /* just the header of flash_block_list */
-       unsigned long num_blocks;
-       struct flash_block_list *next;
-};
 
-static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL};
+static struct flash_block_list *rtas_firmware_flash_list;
 
 /* Use slab cache to guarantee 4k alignment */
 static struct kmem_cache *flash_block_cache = NULL;
@@ -108,13 +104,14 @@ static struct kmem_cache *flash_block_cache = NULL;
 
 /* Local copy of the flash block list.
  * We only allow one open of the flash proc file and create this
- * list as we go.  This list will be put in the
- * rtas_firmware_flash_list var once it is fully read.
+ * list as we go.  The rtas_firmware_flash_list varable will be
+ * set once the data is fully read.
  *
  * For convenience as we build the list we use virtual addrs,
  * we do not fill in the version number, and the length field
  * is treated as the number of entries currently in the block
- * (i.e. not a byte count).  This is all fixed on release.
+ * (i.e. not a byte count).  This is all fixed when calling 
+ * the flash routine.
  */
 
 /* Status int must be first member of struct */
@@ -201,16 +198,16 @@ static int rtas_flash_release(struct inode *inode, struct file *file)
        if (uf->flist) {    
                /* File was opened in write mode for a new flash attempt */
                /* Clear saved list */
-               if (rtas_firmware_flash_list.next) {
-                       free_flash_list(rtas_firmware_flash_list.next);
-                       rtas_firmware_flash_list.next = NULL;
+               if (rtas_firmware_flash_list) {
+                       free_flash_list(rtas_firmware_flash_list);
+                       rtas_firmware_flash_list = NULL;
                }
 
                if (uf->status != FLASH_AUTH)  
                        uf->status = flash_list_valid(uf->flist);
 
                if (uf->status == FLASH_IMG_READY) 
-                       rtas_firmware_flash_list.next = uf->flist;
+                       rtas_firmware_flash_list = uf->flist;
                else
                        free_flash_list(uf->flist);
 
@@ -593,7 +590,7 @@ static void rtas_flash_firmware(int reboot_type)
        unsigned long rtas_block_list;
        int i, status, update_token;
 
-       if (rtas_firmware_flash_list.next == NULL)
+       if (rtas_firmware_flash_list == NULL)
                return;         /* nothing to do */
 
        if (reboot_type != SYS_RESTART) {
@@ -610,20 +607,25 @@ static void rtas_flash_firmware(int reboot_type)
                return;
        }
 
-       /* NOTE: the "first" block list is a global var with no data
-        * blocks in the kernel data segment.  We do this because
-        * we want to ensure this block_list addr is under 4GB.
+       /*
+        * NOTE: the "first" block must be under 4GB, so we create
+        * an entry with no data blocks in the reserved buffer in
+        * the kernel data segment.
         */
-       rtas_firmware_flash_list.num_blocks = 0;
-       flist = (struct flash_block_list *)&rtas_firmware_flash_list;
+       spin_lock(&rtas_data_buf_lock);
+       flist = (struct flash_block_list *)&rtas_data_buf[0];
+       flist->num_blocks = 0;
+       flist->next = rtas_firmware_flash_list;
        rtas_block_list = virt_to_abs(flist);
        if (rtas_block_list >= 4UL*1024*1024*1024) {
                printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
+               spin_unlock(&rtas_data_buf_lock);
                return;
        }
 
        printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
        /* Update the block_list in place. */
+       rtas_firmware_flash_list = NULL; /* too hard to backout on error */
        image_size = 0;
        for (f = flist; f; f = next) {
                /* Translate data addrs to absolute */
@@ -664,6 +666,7 @@ static void rtas_flash_firmware(int reboot_type)
                printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
                break;
        }
+       spin_unlock(&rtas_data_buf_lock);
 }
 
 static void remove_flash_pde(struct proc_dir_entry *dp)
index 8f58986c2ad9a7c56117f24bee6fd089333b80b6..7d84b210f1680de8a41fb23d0ad09a7e19ce905b 100644 (file)
@@ -241,7 +241,6 @@ int __init ppc_init(void)
 
 arch_initcall(ppc_init);
 
-#ifdef CONFIG_IRQSTACKS
 static void __init irqstack_early_init(void)
 {
        unsigned int i;
@@ -255,9 +254,6 @@ static void __init irqstack_early_init(void)
                        __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
        }
 }
-#else
-#define irqstack_early_init()
-#endif
 
 #if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
 static void __init exc_lvl_early_init(void)
index f3fb5a79de52bfecc41d1f42237c10c1bf5168d0..643dcac40fcbc56c8cc3102a74e76a6aae4381eb 100644 (file)
@@ -432,7 +432,6 @@ static u64 slb0_limit(void)
        return 1UL << SID_SHIFT;
 }
 
-#ifdef CONFIG_IRQSTACKS
 static void __init irqstack_early_init(void)
 {
        u64 limit = slb0_limit();
@@ -451,9 +450,6 @@ static void __init irqstack_early_init(void)
                                            THREAD_SIZE, limit));
        }
 }
-#else
-#define irqstack_early_init()
-#endif
 
 #ifdef CONFIG_PPC_BOOK3E
 static void __init exc_lvl_early_init(void)
diff --git a/arch/powerpc/kernel/swsusp_booke.S b/arch/powerpc/kernel/swsusp_booke.S
new file mode 100644 (file)
index 0000000..11a3930
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Based on swsusp_32.S, modified for FSL BookE by
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ * Copyright (c) 2009-2010 MontaVista Software, LLC.
+ */
+
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/mmu.h>
+
+/*
+ * Structure for storing CPU registers on the save area.
+ */
+#define SL_SP          0
+#define SL_PC          4
+#define SL_MSR         8
+#define SL_TCR         0xc
+#define SL_SPRG0       0x10
+#define SL_SPRG1       0x14
+#define SL_SPRG2       0x18
+#define SL_SPRG3       0x1c
+#define SL_SPRG4       0x20
+#define SL_SPRG5       0x24
+#define SL_SPRG6       0x28
+#define SL_SPRG7       0x2c
+#define SL_TBU         0x30
+#define SL_TBL         0x34
+#define SL_R2          0x38
+#define SL_CR          0x3c
+#define SL_LR          0x40
+#define SL_R12         0x44    /* r12 to r31 */
+#define SL_SIZE                (SL_R12 + 80)
+
+       .section .data
+       .align  5
+
+_GLOBAL(swsusp_save_area)
+       .space  SL_SIZE
+
+
+       .section .text
+       .align  5
+
+_GLOBAL(swsusp_arch_suspend)
+       lis     r11,swsusp_save_area@h
+       ori     r11,r11,swsusp_save_area@l
+
+       mflr    r0
+       stw     r0,SL_LR(r11)
+       mfcr    r0
+       stw     r0,SL_CR(r11)
+       stw     r1,SL_SP(r11)
+       stw     r2,SL_R2(r11)
+       stmw    r12,SL_R12(r11)
+
+       /* Save MSR & TCR */
+       mfmsr   r4
+       stw     r4,SL_MSR(r11)
+       mfspr   r4,SPRN_TCR
+       stw     r4,SL_TCR(r11)
+
+       /* Get a stable timebase and save it */
+1:     mfspr   r4,SPRN_TBRU
+       stw     r4,SL_TBU(r11)
+       mfspr   r5,SPRN_TBRL
+       stw     r5,SL_TBL(r11)
+       mfspr   r3,SPRN_TBRU
+       cmpw    r3,r4
+       bne     1b
+
+       /* Save SPRGs */
+       mfsprg  r4,0
+       stw     r4,SL_SPRG0(r11)
+       mfsprg  r4,1
+       stw     r4,SL_SPRG1(r11)
+       mfsprg  r4,2
+       stw     r4,SL_SPRG2(r11)
+       mfsprg  r4,3
+       stw     r4,SL_SPRG3(r11)
+       mfsprg  r4,4
+       stw     r4,SL_SPRG4(r11)
+       mfsprg  r4,5
+       stw     r4,SL_SPRG5(r11)
+       mfsprg  r4,6
+       stw     r4,SL_SPRG6(r11)
+       mfsprg  r4,7
+       stw     r4,SL_SPRG7(r11)
+
+       /* Call the low level suspend stuff (we should probably have made
+        * a stackframe...
+        */
+       bl      swsusp_save
+
+       /* Restore LR from the save area */
+       lis     r11,swsusp_save_area@h
+       ori     r11,r11,swsusp_save_area@l
+       lwz     r0,SL_LR(r11)
+       mtlr    r0
+
+       blr
+
+_GLOBAL(swsusp_arch_resume)
+       sync
+
+       /* Load ptr the list of pages to copy in r3 */
+       lis     r11,(restore_pblist)@h
+       ori     r11,r11,restore_pblist@l
+       lwz     r3,0(r11)
+
+       /* Copy the pages. This is a very basic implementation, to
+        * be replaced by something more cache efficient */
+1:
+       li      r0,256
+       mtctr   r0
+       lwz     r5,pbe_address(r3)      /* source */
+       lwz     r6,pbe_orig_address(r3) /* destination */
+2:
+       lwz     r8,0(r5)
+       lwz     r9,4(r5)
+       lwz     r10,8(r5)
+       lwz     r11,12(r5)
+       addi    r5,r5,16
+       stw     r8,0(r6)
+       stw     r9,4(r6)
+       stw     r10,8(r6)
+       stw     r11,12(r6)
+       addi    r6,r6,16
+       bdnz    2b
+       lwz     r3,pbe_next(r3)
+       cmpwi   0,r3,0
+       bne     1b
+
+       bl flush_dcache_L1
+       bl flush_instruction_cache
+
+       lis     r11,swsusp_save_area@h
+       ori     r11,r11,swsusp_save_area@l
+
+       lwz     r4,SL_SPRG0(r11)
+       mtsprg  0,r4
+       lwz     r4,SL_SPRG1(r11)
+       mtsprg  1,r4
+       lwz     r4,SL_SPRG2(r11)
+       mtsprg  2,r4
+       lwz     r4,SL_SPRG3(r11)
+       mtsprg  3,r4
+       lwz     r4,SL_SPRG4(r11)
+       mtsprg  4,r4
+       lwz     r4,SL_SPRG5(r11)
+       mtsprg  5,r4
+       lwz     r4,SL_SPRG6(r11)
+       mtsprg  6,r4
+       lwz     r4,SL_SPRG7(r11)
+       mtsprg  7,r4
+
+       /* restore the MSR */
+       lwz     r3,SL_MSR(r11)
+       mtmsr   r3
+
+       /* Restore TB */
+       li      r3,0
+       mtspr   SPRN_TBWL,r3
+       lwz     r3,SL_TBU(r11)
+       lwz     r4,SL_TBL(r11)
+       mtspr   SPRN_TBWU,r3
+       mtspr   SPRN_TBWL,r4
+
+       /* Restore TCR and clear any pending bits in TSR. */
+       lwz     r4,SL_TCR(r11)
+       mtspr   SPRN_TCR,r4
+       lis     r4, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h
+       mtspr   SPRN_TSR,r4
+
+       /* Kick decrementer */
+       li      r0,1
+       mtdec   r0
+
+       /* Restore the callee-saved registers and return */
+       lwz     r0,SL_CR(r11)
+       mtcr    r0
+       lwz     r2,SL_R2(r11)
+       lmw     r12,SL_R12(r11)
+       lwz     r1,SL_SP(r11)
+       lwz     r0,SL_LR(r11)
+       mtlr    r0
+
+       li      r3,0
+       blr
index 3031fc712ad03fec600e0caa042c16c5ae6d691a..25fc33984c2bc02d614d641a7668033ba51711bf 100644 (file)
@@ -1,5 +1,6 @@
 /*
  *  Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *  Copyright 2007-2010 Freescale Semiconductor, Inc.
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
@@ -305,7 +306,7 @@ static inline int check_io_access(struct pt_regs *regs)
 #ifndef CONFIG_FSL_BOOKE
 #define get_mc_reason(regs)    ((regs)->dsisr)
 #else
-#define get_mc_reason(regs)    (mfspr(SPRN_MCSR) & MCSR_MASK)
+#define get_mc_reason(regs)    (mfspr(SPRN_MCSR))
 #endif
 #define REASON_FP              ESR_FP
 #define REASON_ILLEGAL         (ESR_PIL | ESR_PUO)
@@ -421,6 +422,91 @@ int machine_check_47x(struct pt_regs *regs)
        return 0;
 }
 #elif defined(CONFIG_E500)
+int machine_check_e500mc(struct pt_regs *regs)
+{
+       unsigned long mcsr = mfspr(SPRN_MCSR);
+       unsigned long reason = mcsr;
+       int recoverable = 1;
+
+       printk("Machine check in kernel mode.\n");
+       printk("Caused by (from MCSR=%lx): ", reason);
+
+       if (reason & MCSR_MCP)
+               printk("Machine Check Signal\n");
+
+       if (reason & MCSR_ICPERR) {
+               printk("Instruction Cache Parity Error\n");
+
+               /*
+                * This is recoverable by invalidating the i-cache.
+                */
+               mtspr(SPRN_L1CSR1, mfspr(SPRN_L1CSR1) | L1CSR1_ICFI);
+               while (mfspr(SPRN_L1CSR1) & L1CSR1_ICFI)
+                       ;
+
+               /*
+                * This will generally be accompanied by an instruction
+                * fetch error report -- only treat MCSR_IF as fatal
+                * if it wasn't due to an L1 parity error.
+                */
+               reason &= ~MCSR_IF;
+       }
+
+       if (reason & MCSR_DCPERR_MC) {
+               printk("Data Cache Parity Error\n");
+               recoverable = 0;
+       }
+
+       if (reason & MCSR_L2MMU_MHIT) {
+               printk("Hit on multiple TLB entries\n");
+               recoverable = 0;
+       }
+
+       if (reason & MCSR_NMI)
+               printk("Non-maskable interrupt\n");
+
+       if (reason & MCSR_IF) {
+               printk("Instruction Fetch Error Report\n");
+               recoverable = 0;
+       }
+
+       if (reason & MCSR_LD) {
+               printk("Load Error Report\n");
+               recoverable = 0;
+       }
+
+       if (reason & MCSR_ST) {
+               printk("Store Error Report\n");
+               recoverable = 0;
+       }
+
+       if (reason & MCSR_LDG) {
+               printk("Guarded Load Error Report\n");
+               recoverable = 0;
+       }
+
+       if (reason & MCSR_TLBSYNC)
+               printk("Simultaneous tlbsync operations\n");
+
+       if (reason & MCSR_BSL2_ERR) {
+               printk("Level 2 Cache Error\n");
+               recoverable = 0;
+       }
+
+       if (reason & MCSR_MAV) {
+               u64 addr;
+
+               addr = mfspr(SPRN_MCAR);
+               addr |= (u64)mfspr(SPRN_MCARU) << 32;
+
+               printk("Machine Check %s Address: %#llx\n",
+                      reason & MCSR_MEA ? "Effective" : "Physical", addr);
+       }
+
+       mtspr(SPRN_MCSR, mcsr);
+       return mfspr(SPRN_MCSR) == 0 && recoverable;
+}
+
 int machine_check_e500(struct pt_regs *regs)
 {
        unsigned long reason = get_mc_reason(regs);
index dcd01c82e7013c8e08f797eaa40c9543d5f2fc01..8a0deefac08d216c2ebd127add50ce8117f74f79 100644 (file)
@@ -223,19 +223,17 @@ SECTIONS
 #endif
 
        /* The initial task and kernel stack */
-       .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
-               INIT_TASK_DATA(THREAD_SIZE)
-       }
+       INIT_TASK_DATA_SECTION(THREAD_SIZE)
 
-       .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+       .data..page_aligned : AT(ADDR(.data..page_aligned) - LOAD_OFFSET) {
                PAGE_ALIGNED_DATA(PAGE_SIZE)
        }
 
-       .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
+       .data..cacheline_aligned : AT(ADDR(.data..cacheline_aligned) - LOAD_OFFSET) {
                CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
        }
 
-       .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
+       .data..read_mostly : AT(ADDR(.data..read_mostly) - LOAD_OFFSET) {
                READ_MOSTLY_DATA(L1_CACHE_BYTES)
        }
 
index bc2b4004eb265a70ea4b082693e0b9eb9cf49e3f..e8a00b0c444912d3b1bd0b300e9869942dc48198 100644 (file)
@@ -164,7 +164,7 @@ static int __init kvmppc_e500_init(void)
        return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE);
 }
 
-static void __init kvmppc_e500_exit(void)
+static void __exit kvmppc_e500_exit(void)
 {
        kvmppc_booke_exit();
 }
index 9fc02dc72ce9e98a5bdcc238a8e152c35a6be5f7..34347b2e7e313995c803d34c847034dff7a9c1cf 100644 (file)
@@ -115,11 +115,7 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
        struct page *ptepage;
 
-#ifdef CONFIG_HIGHPTE
-       gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT | __GFP_ZERO;
-#else
        gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
-#endif
 
        ptepage = alloc_pages(flags, 0);
        if (!ptepage)
index eeba0a70e466f6d4d293fdaba9bc0cdf27af4c07..69d668c072aeab579aab54182d0c9bd544dac956 100644 (file)
@@ -171,6 +171,17 @@ config ISS4xx
        help
          This option enables support for the IBM ISS simulation environment
 
+config ICON
+       bool "Icon"
+       depends on 44x
+       default n
+       select PPC44x_SIMPLE
+       select 440SPe
+       select PCI
+       select PPC4xx_PCI_EXPRESS
+       help
+         This option enables support for the AMCC PPC440SPe evaluation board.
+
 #config LUAN
 #      bool "Luan"
 #      depends on 44x
index e8c23ccaa1fcfc628744d4490f408860352d0969..5f7a29d7f59091fa958e063b661421aa447e48fa 100644 (file)
@@ -61,7 +61,8 @@ static char *board[] __initdata = {
        "amcc,redwood",
        "amcc,sequoia",
        "amcc,taishan",
-       "amcc,yosemite"
+       "amcc,yosemite",
+       "mosaixtech,icon"
 };
 
 static int __init ppc44x_probe(void)
index a55b0b6813ed2a9f249a2051e861176e572a6d59..76722532bd95e516955397c5a81d651159cddc2e 100644 (file)
@@ -64,10 +64,19 @@ int mpc52xx_pm_prepare(void)
                { .type = "builtin", .compatible = "mpc5200", }, /* efika */
                {}
        };
+       struct resource res;
 
        /* map the whole register space */
        np = of_find_matching_node(NULL, immr_ids);
-       mbar = of_iomap(np, 0);
+
+       if (of_address_to_resource(np, 0, &res)) {
+               pr_err("mpc52xx_pm_prepare(): could not get IMMR address\n");
+               of_node_put(np);
+               return -ENOSYS;
+       }
+
+       mbar = ioremap(res.start, 0xc000); /* we should map whole region including SRAM */
+
        of_node_put(np);
        if (!mbar) {
                pr_err("mpc52xx_pm_prepare(): could not map registers\n");
index f0684c8ac960ef602726f012715772c672628745..8fe87fc61485bdc1c48c4bf430ed626933ce8b22 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) Freescale Semicondutor, Inc. 2006-2007. All rights reserved.
+ * Copyright (C) Freescale Semicondutor, Inc. 2006-2010. All rights reserved.
  *
  * Author: Andy Fleming <afleming@freescale.com>
  *
@@ -154,6 +154,10 @@ static int mpc8568_mds_phy_fixups(struct phy_device *phydev)
  * Setup the architecture
  *
  */
+#ifdef CONFIG_SMP
+extern void __init mpc85xx_smp_init(void);
+#endif
+
 static void __init mpc85xx_mds_setup_arch(void)
 {
        struct device_node *np;
@@ -194,6 +198,10 @@ static void __init mpc85xx_mds_setup_arch(void)
        }
 #endif
 
+#ifdef CONFIG_SMP
+       mpc85xx_smp_init();
+#endif
+
 #ifdef CONFIG_QUICC_ENGINE
        np = of_find_compatible_node(NULL, NULL, "fsl,qe");
        if (!np) {
@@ -271,9 +279,49 @@ static void __init mpc85xx_mds_setup_arch(void)
                                                BCSR_UCC_RGMII, BCSR_UCC_RTBI);
                        }
 
+               } else if (machine_is(p1021_mds)) {
+#define BCSR11_ENET_MICRST     (0x1 << 5)
+                       /* Reset Micrel PHY */
+                       clrbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
+                       setbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
                }
+
                iounmap(bcsr_regs);
        }
+
+       if (machine_is(p1021_mds)) {
+#define MPC85xx_PMUXCR_OFFSET           0x60
+#define MPC85xx_PMUXCR_QE0              0x00008000
+#define MPC85xx_PMUXCR_QE3              0x00001000
+#define MPC85xx_PMUXCR_QE9              0x00000040
+#define MPC85xx_PMUXCR_QE12             0x00000008
+               static __be32 __iomem *pmuxcr;
+
+               np = of_find_node_by_name(NULL, "global-utilities");
+
+               if (np) {
+                       pmuxcr = of_iomap(np, 0) + MPC85xx_PMUXCR_OFFSET;
+
+                       if (!pmuxcr)
+                               printk(KERN_EMERG "Error: Alternate function"
+                                       " signal multiplex control register not"
+                                       " mapped!\n");
+                       else
+                       /* P1021 has pins muxed for QE and other functions. To
+                        * enable QE UEC mode, we need to set bit QE0 for UCC1
+                        * in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
+                        * and QE12 for QE MII management singals in PMUXCR
+                        * register.
+                        */
+                               setbits32(pmuxcr, MPC85xx_PMUXCR_QE0 |
+                                                 MPC85xx_PMUXCR_QE3 |
+                                                 MPC85xx_PMUXCR_QE9 |
+                                                 MPC85xx_PMUXCR_QE12);
+
+                       of_node_put(np);
+               }
+
+       }
 #endif /* CONFIG_QUICC_ENGINE */
 
 #ifdef CONFIG_SWIOTLB
@@ -330,6 +378,16 @@ static struct of_device_id mpc85xx_ids[] = {
        {},
 };
 
+static struct of_device_id p1021_ids[] = {
+       { .type = "soc", },
+       { .compatible = "soc", },
+       { .compatible = "simple-bus", },
+       { .type = "qe", },
+       { .compatible = "fsl,qe", },
+       { .compatible = "gianfar", },
+       {},
+};
+
 static int __init mpc85xx_publish_devices(void)
 {
        if (machine_is(mpc8568_mds))
@@ -342,11 +400,22 @@ static int __init mpc85xx_publish_devices(void)
 
        return 0;
 }
+
+static int __init p1021_publish_devices(void)
+{
+       /* Publish the QE devices */
+       of_platform_bus_probe(NULL, p1021_ids, NULL);
+
+       return 0;
+}
+
 machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
 machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices);
+machine_device_initcall(p1021_mds, p1021_publish_devices);
 
 machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier);
 machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier);
+machine_arch_initcall(p1021_mds, swiotlb_setup_bus_notifier);
 
 static void __init mpc85xx_mds_pic_init(void)
 {
@@ -366,7 +435,7 @@ static void __init mpc85xx_mds_pic_init(void)
 
        mpic = mpic_alloc(np, r.start,
                        MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN |
-                       MPIC_BROKEN_FRR_NIRQS,
+                       MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
                        0, 256, " OpenPIC  ");
        BUG_ON(mpic == NULL);
        of_node_put(np);
@@ -380,7 +449,11 @@ static void __init mpc85xx_mds_pic_init(void)
                if (!np)
                        return;
        }
-       qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL);
+       if (machine_is(p1021_mds))
+               qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
+                               qe_ic_cascade_high_mpic);
+       else
+               qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL);
        of_node_put(np);
 #endif                         /* CONFIG_QUICC_ENGINE */
 }
@@ -426,3 +499,26 @@ define_machine(mpc8569_mds) {
        .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
 #endif
 };
+
+static int __init p1021_mds_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       return of_flat_dt_is_compatible(root, "fsl,P1021MDS");
+
+}
+
+define_machine(p1021_mds) {
+       .name           = "P1021 MDS",
+       .probe          = p1021_mds_probe,
+       .setup_arch     = mpc85xx_mds_setup_arch,
+       .init_IRQ       = mpc85xx_mds_pic_init,
+       .get_irq        = mpic_get_irq,
+       .restart        = fsl_rstcr_restart,
+       .calibrate_decr = generic_calibrate_decr,
+       .progress       = udbg_progress,
+#ifdef CONFIG_PCI
+       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
+#endif
+};
+
index 22667a09d40eee6276eff723a8e4523e2b2e5bd2..4326b737d913e02d4541320c5bb3cecc45f7220b 100644 (file)
@@ -1066,7 +1066,7 @@ static int __init cell_iommu_fixed_mapping_init(void)
        fbase = _ALIGN_UP(fbase, 1 << IO_SEGMENT_SHIFT);
        fsize = lmb_phys_mem_size();
 
-       if ((fbase + fsize) <= 0x800000000)
+       if ((fbase + fsize) <= 0x800000000ul)
                hbase = 0; /* use the device tree window */
        else {
                /* If we're over 32 GB we need to cheat. We can't map all of
index a7be144f5874335da103e0af4c33b3b3d1e1f3fe..962c2d8dd8d927e0d2e03336dff954e42935ef86 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2007-2010 Freescale Semiconductor, Inc.
  *
  * Author: Tony Li <tony.li@freescale.com>
  *        Jason Jin <Jason.jin@freescale.com>
 #include <asm/prom.h>
 #include <asm/hw_irq.h>
 #include <asm/ppc-pci.h>
+#include <asm/mpic.h>
 #include "fsl_msi.h"
 
+LIST_HEAD(msi_head);
+
 struct fsl_msi_feature {
        u32 fsl_pic_ip;
        u32 msiir_offset;
 };
 
-static struct fsl_msi *fsl_msi;
+struct fsl_msi_cascade_data {
+       struct fsl_msi *msi_data;
+       int index;
+};
 
 static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg)
 {
@@ -54,10 +60,12 @@ static struct irq_chip fsl_msi_chip = {
 static int fsl_msi_host_map(struct irq_host *h, unsigned int virq,
                                irq_hw_number_t hw)
 {
+       struct fsl_msi *msi_data = h->host_data;
        struct irq_chip *chip = &fsl_msi_chip;
 
        irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
 
+       set_irq_chip_data(virq, msi_data);
        set_irq_chip_and_handler(virq, chip, handle_edge_irq);
 
        return 0;
@@ -96,11 +104,12 @@ static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
 static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
 {
        struct msi_desc *entry;
-       struct fsl_msi *msi_data = fsl_msi;
+       struct fsl_msi *msi_data;
 
        list_for_each_entry(entry, &pdev->msi_list, list) {
                if (entry->irq == NO_IRQ)
                        continue;
+               msi_data = get_irq_data(entry->irq);
                set_irq_msi(entry->irq, NULL);
                msi_bitmap_free_hwirqs(&msi_data->bitmap,
                                       virq_to_hw(entry->irq), 1);
@@ -111,9 +120,10 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
 }
 
 static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
-                                 struct msi_msg *msg)
+                               struct msi_msg *msg,
+                               struct fsl_msi *fsl_msi_data)
 {
-       struct fsl_msi *msi_data = fsl_msi;
+       struct fsl_msi *msi_data = fsl_msi_data;
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
        u32 base = 0;
 
@@ -130,14 +140,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
 
 static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 {
-       int rc, hwirq;
+       int rc, hwirq = -ENOMEM;
        unsigned int virq;
        struct msi_desc *entry;
        struct msi_msg msg;
-       struct fsl_msi *msi_data = fsl_msi;
+       struct fsl_msi *msi_data;
 
        list_for_each_entry(entry, &pdev->msi_list, list) {
-               hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
+               list_for_each_entry(msi_data, &msi_head, list) {
+                       hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
+                       if (hwirq >= 0)
+                               break;
+               }
+
                if (hwirq < 0) {
                        rc = hwirq;
                        pr_debug("%s: fail allocating msi interrupt\n",
@@ -154,25 +169,31 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                        rc = -ENOSPC;
                        goto out_free;
                }
+               set_irq_data(virq, msi_data);
                set_irq_msi(virq, entry);
 
-               fsl_compose_msi_msg(pdev, hwirq, &msg);
+               fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data);
                write_msi_msg(virq, &msg);
        }
        return 0;
 
 out_free:
+       /* free by the caller of this function */
        return rc;
 }
 
 static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 {
        unsigned int cascade_irq;
-       struct fsl_msi *msi_data = fsl_msi;
+       struct fsl_msi *msi_data;
        int msir_index = -1;
        u32 msir_value = 0;
        u32 intr_index;
        u32 have_shift = 0;
+       struct fsl_msi_cascade_data *cascade_data;
+
+       cascade_data = (struct fsl_msi_cascade_data *)get_irq_data(irq);
+       msi_data = cascade_data->msi_data;
 
        raw_spin_lock(&desc->lock);
        if ((msi_data->feature &  FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) {
@@ -187,13 +208,13 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
        if (unlikely(desc->status & IRQ_INPROGRESS))
                goto unlock;
 
-       msir_index = (int)desc->handler_data;
+       msir_index = cascade_data->index;
 
        if (msir_index >= NR_MSI_REG)
                cascade_irq = NO_IRQ;
 
        desc->status |= IRQ_INPROGRESS;
-       switch (fsl_msi->feature & FSL_PIC_IP_MASK) {
+       switch (msi_data->feature & FSL_PIC_IP_MASK) {
        case FSL_PIC_IP_MPIC:
                msir_value = fsl_msi_read(msi_data->msi_regs,
                        msir_index * 0x10);
@@ -229,6 +250,30 @@ unlock:
        raw_spin_unlock(&desc->lock);
 }
 
+static int fsl_of_msi_remove(struct of_device *ofdev)
+{
+       struct fsl_msi *msi = ofdev->dev.platform_data;
+       int virq, i;
+       struct fsl_msi_cascade_data *cascade_data;
+
+       if (msi->list.prev != NULL)
+               list_del(&msi->list);
+       for (i = 0; i < NR_MSI_REG; i++) {
+               virq = msi->msi_virqs[i];
+               if (virq != NO_IRQ) {
+                       cascade_data = get_irq_data(virq);
+                       kfree(cascade_data);
+                       irq_dispose_mapping(virq);
+               }
+       }
+       if (msi->bitmap.bitmap)
+               msi_bitmap_free(&msi->bitmap);
+       iounmap(msi->msi_regs);
+       kfree(msi);
+
+       return 0;
+}
+
 static int __devinit fsl_of_msi_probe(struct of_device *dev,
                                const struct of_device_id *match)
 {
@@ -239,15 +284,18 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
        int virt_msir;
        const u32 *p;
        struct fsl_msi_feature *features = match->data;
+       struct fsl_msi_cascade_data *cascade_data = NULL;
+       int len;
+       u32 offset;
 
        printk(KERN_DEBUG "Setting up Freescale MSI support\n");
 
        msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL);
        if (!msi) {
                dev_err(&dev->dev, "No memory for MSI structure\n");
-               err = -ENOMEM;
-               goto error_out;
+               return -ENOMEM;
        }
+       dev->dev.platform_data = msi;
 
        msi->irqhost = irq_alloc_host(dev->dev.of_node, IRQ_HOST_MAP_LINEAR,
                                      NR_MSI_IRQS, &fsl_msi_host_ops, 0);
@@ -298,27 +346,47 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
                err = -EINVAL;
                goto error_out;
        }
+       offset = 0;
+       p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
+       if (p)
+               offset = *p / IRQS_PER_MSI_REG;
 
        count /= sizeof(u32);
-       for (i = 0; i < count / 2; i++) {
-               if (i > NR_MSI_REG)
-                       break;
+       for (i = 0; i < min(count / 2, NR_MSI_REG); i++) {
                virt_msir = irq_of_parse_and_map(dev->dev.of_node, i);
                if (virt_msir != NO_IRQ) {
-                       set_irq_data(virt_msir, (void *)i);
+                       cascade_data = kzalloc(
+                                       sizeof(struct fsl_msi_cascade_data),
+                                       GFP_KERNEL);
+                       if (!cascade_data) {
+                               dev_err(&dev->dev,
+                                       "No memory for MSI cascade data\n");
+                               err = -ENOMEM;
+                               goto error_out;
+                       }
+                       msi->msi_virqs[i] = virt_msir;
+                       cascade_data->index = i + offset;
+                       cascade_data->msi_data = msi;
+                       set_irq_data(virt_msir, (void *)cascade_data);
                        set_irq_chained_handler(virt_msir, fsl_msi_cascade);
                }
        }
 
-       fsl_msi = msi;
+       list_add_tail(&msi->list, &msi_head);
 
-       WARN_ON(ppc_md.setup_msi_irqs);
-       ppc_md.setup_msi_irqs = fsl_setup_msi_irqs;
-       ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs;
-       ppc_md.msi_check_device = fsl_msi_check_device;
+       /* The multiple setting ppc_md.setup_msi_irqs will not harm things */
+       if (!ppc_md.setup_msi_irqs) {
+               ppc_md.setup_msi_irqs = fsl_setup_msi_irqs;
+               ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs;
+               ppc_md.msi_check_device = fsl_msi_check_device;
+       } else if (ppc_md.setup_msi_irqs != fsl_setup_msi_irqs) {
+               dev_err(&dev->dev, "Different MSI driver already installed!\n");
+               err = -ENODEV;
+               goto error_out;
+       }
        return 0;
 error_out:
-       kfree(msi);
+       fsl_of_msi_remove(dev);
        return err;
 }
 
@@ -351,6 +419,7 @@ static struct of_platform_driver fsl_of_msi_driver = {
                .of_match_table = fsl_of_msi_ids,
        },
        .probe = fsl_of_msi_probe,
+       .remove = fsl_of_msi_remove,
 };
 
 static __init int fsl_of_msi_init(void)
index 331c7e7025b786bf7d3ed071038ceb6330f971fc..624580c252d75029a9f551f53a6c8efca973c4bd 100644 (file)
@@ -32,8 +32,11 @@ struct fsl_msi {
        u32 msi_addr_hi;
        void __iomem *msi_regs;
        u32 feature;
+       int msi_virqs[NR_MSI_REG];
 
        struct msi_bitmap bitmap;
+
+       struct list_head list;          /* support multiple MSI banks */
 };
 
 #endif /* _POWERPC_SYSDEV_FSL_MSI_H */
index cd37e49e70349d05cc82c48e83b0bd6a42faa9ce..30e1626b2e850c9f2d5f9d2137f3025cf05f4ea8 100644 (file)
@@ -1426,7 +1426,7 @@ int fsl_rio_setup(struct of_device *dev)
        port->iores.flags = IORESOURCE_MEM;
        port->iores.name = "rio_io_win";
 
-       priv->pwirq   = irq_of_parse_and_map(dev->node, 0);
+       priv->pwirq   = irq_of_parse_and_map(dev->dev.of_node, 0);
        priv->bellirq = irq_of_parse_and_map(dev->dev.of_node, 2);
        priv->txirq = irq_of_parse_and_map(dev->dev.of_node, 3);
        priv->rxirq = irq_of_parse_and_map(dev->dev.of_node, 4);
index 2102487612a428cdac78735021d55629fc7f369a..20b73c025a4566e599f46192fed18df2ed002fda 100644 (file)
@@ -1666,7 +1666,7 @@ static int mpic_resume(struct sys_device *dev)
                               mpic->save_data[i].dest);
 
 #ifdef CONFIG_MPIC_U3_HT_IRQS
-       {
+       if (mpic->fixups) {
                struct mpic_irq_fixup *fixup = &mpic->fixups[i];
 
                if (fixup->base) {
index 106d767bf65bfd1c7d4e7332d6459de8a338eec4..156aa7d362584048945c8f10475edcf801eb0e8b 100644 (file)
@@ -974,6 +974,123 @@ static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =
        .setup_utl      = ppc460ex_pciex_init_utl,
 };
 
+static int __init ppc460sx_pciex_core_init(struct device_node *np)
+{
+       /* HSS drive amplitude */
+       mtdcri(SDR0, PESDR0_460SX_HSSL0DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR0_460SX_HSSL1DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR0_460SX_HSSL2DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR0_460SX_HSSL3DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR0_460SX_HSSL4DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR0_460SX_HSSL5DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR0_460SX_HSSL6DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR0_460SX_HSSL7DAMP, 0xB9843211);
+
+       mtdcri(SDR0, PESDR1_460SX_HSSL0DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR1_460SX_HSSL1DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR1_460SX_HSSL2DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR1_460SX_HSSL3DAMP, 0xB9843211);
+
+       mtdcri(SDR0, PESDR2_460SX_HSSL0DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR2_460SX_HSSL1DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR2_460SX_HSSL2DAMP, 0xB9843211);
+       mtdcri(SDR0, PESDR2_460SX_HSSL3DAMP, 0xB9843211);
+
+       /* HSS TX pre-emphasis */
+       mtdcri(SDR0, PESDR0_460SX_HSSL0COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR0_460SX_HSSL1COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR0_460SX_HSSL2COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR0_460SX_HSSL3COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR0_460SX_HSSL4COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR0_460SX_HSSL5COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR0_460SX_HSSL6COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR0_460SX_HSSL7COEFA, 0xDCB98987);
+
+       mtdcri(SDR0, PESDR1_460SX_HSSL0COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR1_460SX_HSSL1COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR1_460SX_HSSL2COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR1_460SX_HSSL3COEFA, 0xDCB98987);
+
+       mtdcri(SDR0, PESDR2_460SX_HSSL0COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR2_460SX_HSSL1COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR2_460SX_HSSL2COEFA, 0xDCB98987);
+       mtdcri(SDR0, PESDR2_460SX_HSSL3COEFA, 0xDCB98987);
+
+       /* HSS TX calibration control */
+       mtdcri(SDR0, PESDR0_460SX_HSSL1CALDRV, 0x22222222);
+       mtdcri(SDR0, PESDR1_460SX_HSSL1CALDRV, 0x22220000);
+       mtdcri(SDR0, PESDR2_460SX_HSSL1CALDRV, 0x22220000);
+
+       /* HSS TX slew control */
+       mtdcri(SDR0, PESDR0_460SX_HSSSLEW, 0xFFFFFFFF);
+       mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000);
+       mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000);
+
+       udelay(100);
+
+       /* De-assert PLLRESET */
+       dcri_clrset(SDR0, PESDR0_PLLLCT2, 0x00000100, 0);
+
+       /* Reset DL, UTL, GPL before configuration */
+       mtdcri(SDR0, PESDR0_460SX_RCSSET,
+                       PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
+       mtdcri(SDR0, PESDR1_460SX_RCSSET,
+                       PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
+       mtdcri(SDR0, PESDR2_460SX_RCSSET,
+                       PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
+
+       udelay(100);
+
+       /*
+        * If bifurcation is not enabled, u-boot would have disabled the
+        * third PCIe port
+        */
+       if (((mfdcri(SDR0, PESDR1_460SX_HSSCTLSET) & 0x00000001) ==
+                               0x00000001)) {
+               printk(KERN_INFO "PCI: PCIE bifurcation setup successfully.\n");
+               printk(KERN_INFO "PCI: Total 3 PCIE ports are present\n");
+               return 3;
+       }
+
+       printk(KERN_INFO "PCI: Total 2 PCIE ports are present\n");
+       return 2;
+}
+
+static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+{
+
+       if (port->endpoint)
+               dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
+                               0x01000000, 0);
+       else
+               dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
+                               0, 0x01000000);
+
+       /*Gen-1*/
+       mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000);
+
+       dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
+                       (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL),
+                       PESDRx_RCSSET_RSTPYN);
+
+       port->has_ibpre = 1;
+
+       return 0;
+}
+
+static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)
+{
+       /* Max 128 Bytes */
+       out_be32 (port->utl_base + PEUTL_PBBSZ,   0x00000000);
+       return 0;
+}
+
+static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
+       .core_init      = ppc460sx_pciex_core_init,
+       .port_init_hw   = ppc460sx_pciex_init_port_hw,
+       .setup_utl      = ppc460sx_pciex_init_utl,
+};
+
 #endif /* CONFIG_44x */
 
 #ifdef CONFIG_40x
@@ -1089,6 +1206,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
        }
        if (of_device_is_compatible(np, "ibm,plb-pciex-460ex"))
                ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops;
+       if (of_device_is_compatible(np, "ibm,plb-pciex-460sx"))
+               ppc4xx_pciex_hwops = &ppc460sx_pcie_hwops;
 #endif /* CONFIG_44x    */
 #ifdef CONFIG_40x
        if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
index d04e40b306fbdfdaf254a16993f4eb79431e3c96..56d9e5deccbf5e7ccff3e6b1cc62ef23b9e10a9c 100644 (file)
 #define PESDR0_460EX_IHS1              0x036C
 #define PESDR0_460EX_IHS2              0x036D
 
+/*
+ * 460SX addtional DCRs
+ */
+#define PESDRn_460SX_RCEI              0x02
+
+#define PESDR0_460SX_HSSL0DAMP         0x320
+#define PESDR0_460SX_HSSL1DAMP         0x321
+#define PESDR0_460SX_HSSL2DAMP         0x322
+#define PESDR0_460SX_HSSL3DAMP         0x323
+#define PESDR0_460SX_HSSL4DAMP         0x324
+#define PESDR0_460SX_HSSL5DAMP         0x325
+#define PESDR0_460SX_HSSL6DAMP         0x326
+#define PESDR0_460SX_HSSL7DAMP         0x327
+
+#define PESDR1_460SX_HSSL0DAMP         0x354
+#define PESDR1_460SX_HSSL1DAMP         0x355
+#define PESDR1_460SX_HSSL2DAMP         0x356
+#define PESDR1_460SX_HSSL3DAMP         0x357
+
+#define PESDR2_460SX_HSSL0DAMP         0x384
+#define PESDR2_460SX_HSSL1DAMP         0x385
+#define PESDR2_460SX_HSSL2DAMP         0x386
+#define PESDR2_460SX_HSSL3DAMP         0x387
+
+#define PESDR0_460SX_HSSL0COEFA                0x328
+#define PESDR0_460SX_HSSL1COEFA                0x329
+#define PESDR0_460SX_HSSL2COEFA                0x32A
+#define PESDR0_460SX_HSSL3COEFA                0x32B
+#define PESDR0_460SX_HSSL4COEFA                0x32C
+#define PESDR0_460SX_HSSL5COEFA                0x32D
+#define PESDR0_460SX_HSSL6COEFA                0x32E
+#define PESDR0_460SX_HSSL7COEFA                0x32F
+
+#define PESDR1_460SX_HSSL0COEFA                0x358
+#define PESDR1_460SX_HSSL1COEFA                0x359
+#define PESDR1_460SX_HSSL2COEFA                0x35A
+#define PESDR1_460SX_HSSL3COEFA                0x35B
+
+#define PESDR2_460SX_HSSL0COEFA                0x388
+#define PESDR2_460SX_HSSL1COEFA                0x389
+#define PESDR2_460SX_HSSL2COEFA                0x38A
+#define PESDR2_460SX_HSSL3COEFA                0x38B
+
+#define PESDR0_460SX_HSSL1CALDRV       0x339
+#define PESDR1_460SX_HSSL1CALDRV       0x361
+#define PESDR2_460SX_HSSL1CALDRV       0x391
+
+#define PESDR0_460SX_HSSSLEW           0x338
+#define PESDR1_460SX_HSSSLEW           0x360
+#define PESDR2_460SX_HSSSLEW           0x390
+
+#define PESDR0_460SX_HSSCTLSET         0x31E
+#define PESDR1_460SX_HSSCTLSET         0x352
+#define PESDR2_460SX_HSSCTLSET         0x382
+
+#define PESDR0_460SX_RCSSET            0x304
+#define PESDR1_460SX_RCSSET            0x344
+#define PESDR2_460SX_RCSSET            0x374
 /*
  * Of the above, some are common offsets from the base
  */
index 55c80ffd42b9b9ef5a4fb7e3768c4b2deb462e83..92f1cb745d6946c603586820a4daed13b461d7a3 100644 (file)
@@ -181,7 +181,7 @@ static int __init appldata_os_init(void)
                goto out;
        }
 
-       appldata_os_data = kzalloc(max_size, GFP_DMA);
+       appldata_os_data = kzalloc(max_size, GFP_KERNEL | GFP_DMA);
        if (appldata_os_data == NULL) {
                rc = -ENOMEM;
                goto out;
index bcd6884985ad53ec8ebb758c3b050c15c28228c9..253f158db668c51269c0a6d9245ae6da52991166 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.34-rc3
-# Fri Apr  9 09:57:10 2010
+# Linux kernel version: 2.6.35-rc1
+# Fri Jun  4 11:32:40 2010
 #
 CONFIG_SCHED_MC=y
 CONFIG_MMU=y
@@ -35,11 +35,13 @@ CONFIG_CONSTRUCTORS=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_HAVE_KERNEL_GZIP=y
 CONFIG_HAVE_KERNEL_BZIP2=y
 CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
 CONFIG_KERNEL_GZIP=y
 # CONFIG_KERNEL_BZIP2 is not set
 # CONFIG_KERNEL_LZMA is not set
@@ -77,6 +79,7 @@ CONFIG_CGROUP_NS=y
 # CONFIG_CGROUP_CPUACCT is not set
 # CONFIG_RESOURCE_COUNTERS is not set
 # CONFIG_CGROUP_SCHED is not set
+# CONFIG_BLK_CGROUP is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
@@ -157,7 +160,6 @@ CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
 CONFIG_BLK_DEV_BSG=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
-# CONFIG_BLK_CGROUP is not set
 CONFIG_BLOCK_COMPAT=y
 
 #
@@ -166,7 +168,6 @@ CONFIG_BLOCK_COMPAT=y
 CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-# CONFIG_CFQ_GROUP_IOSCHED is not set
 CONFIG_DEFAULT_DEADLINE=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
@@ -247,7 +248,6 @@ CONFIG_64BIT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 CONFIG_HOTPLUG_CPU=y
-# CONFIG_SCHED_BOOK is not set
 CONFIG_COMPAT=y
 CONFIG_SYSVIPC_COMPAT=y
 CONFIG_AUDIT_ARCH=y
@@ -320,7 +320,6 @@ CONFIG_COMPAT_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_FORCE_MAX_ZONEORDER=9
-# CONFIG_PROCESS_DEBUG is not set
 CONFIG_PFAULT=y
 # CONFIG_SHARED_KERNEL is not set
 # CONFIG_CMM is not set
@@ -457,6 +456,7 @@ CONFIG_NF_CONNTRACK=m
 # CONFIG_IP6_NF_IPTABLES is not set
 # CONFIG_IP_DCCP is not set
 CONFIG_IP_SCTP=m
+# CONFIG_NET_SCTPPROBE is not set
 # CONFIG_SCTP_DBG_MSG is not set
 # CONFIG_SCTP_DBG_OBJCNT is not set
 # CONFIG_SCTP_HMAC_NONE is not set
@@ -465,6 +465,7 @@ CONFIG_SCTP_HMAC_MD5=y
 # 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_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
@@ -525,6 +526,7 @@ CONFIG_NET_ACT_NAT=m
 # CONFIG_NET_CLS_IND is not set
 CONFIG_NET_SCH_FIFO=y
 # CONFIG_DCB is not set
+CONFIG_RPS=y
 
 #
 # Network testing
@@ -546,6 +548,7 @@ CONFIG_CAN_VCAN=m
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
 # CONFIG_PCMCIA is not set
 CONFIG_CCW=y
 
@@ -728,6 +731,7 @@ CONFIG_VIRTIO_NET=m
 # Character devices
 #
 CONFIG_DEVKMEM=y
+# CONFIG_N_GSM is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
@@ -775,6 +779,7 @@ CONFIG_S390_TAPE_34XX=m
 # CONFIG_MONREADER is not set
 CONFIG_MONWRITER=m
 CONFIG_S390_VMUR=m
+# CONFIG_RAMOOPS is not set
 
 #
 # PPS support
@@ -788,10 +793,6 @@ CONFIG_S390_VMUR=m
 # CONFIG_NEW_LEDS is not set
 CONFIG_ACCESSIBILITY=y
 # CONFIG_AUXDISPLAY is not set
-
-#
-# TI VLYNQ
-#
 # CONFIG_STAGING is not set
 
 #
@@ -976,6 +977,7 @@ CONFIG_DEBUG_MEMORY_INIT=y
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
 # CONFIG_LKDTM is not set
+# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
@@ -1010,6 +1012,7 @@ CONFIG_BRANCH_PROFILE_NONE=y
 CONFIG_KPROBE_EVENT=y
 # CONFIG_RING_BUFFER_BENCHMARK is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
 CONFIG_SAMPLES=y
 # CONFIG_SAMPLE_TRACEPOINTS is not set
 # CONFIG_SAMPLE_TRACE_EVENTS is not set
index 9b866816863c89a76069d1d3b9f857067a1aa27f..24aafa68b64367a8ff1e68c91981d15c2ee51afd 100644 (file)
@@ -14,6 +14,6 @@
 #define L1_CACHE_BYTES     256
 #define L1_CACHE_SHIFT     8
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #endif
index 639380a0c45c6278db26a03ea7b39eeec8fc48f2..22cfd634c35531b7f8a1d4057f92b4af72e20d1a 100644 (file)
@@ -55,8 +55,10 @@ void *module_alloc(unsigned long size)
 /* Free memory returned from module_alloc */
 void module_free(struct module *mod, void *module_region)
 {
-       vfree(mod->arch.syminfo);
-       mod->arch.syminfo = NULL;
+       if (mod) {
+               vfree(mod->arch.syminfo);
+               mod->arch.syminfo = NULL;
+       }
        vfree(module_region);
 }
 
index c56d3f56d020224583bfcee76790dd761fa39c78..1f066e46e83e69775e8494023feae5f7b337d685 100644 (file)
@@ -264,7 +264,7 @@ restore_registers:
        lghi    %r2,0
        br      %r14
 
-       .section .data.nosave,"aw",@progbits
+       .section .data..nosave,"aw",@progbits
        .align  8
 .Ldisabled_wait_31:
        .long  0x000a0000,0x00000000
index 8093e6f47f49735d978f19ff4ea40db7ab797313..ae3705816878f7a7eb4195ff4001ec136a567d2f 100644 (file)
@@ -761,7 +761,7 @@ static int __init kvm_s390_init(void)
         * to hold the maximum amount of facilites. On the other hand, we
         * only set facilities that are known to work in KVM.
         */
-       facilities = (unsigned long long *) get_zeroed_page(GFP_DMA);
+       facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA);
        if (!facilities) {
                kvm_exit();
                return -ENOMEM;
index eff3c5989b46b1135336cb806794febeebf6c905..702276f5e2fa4a25c0507e70ddde359916a971f6 100644 (file)
@@ -113,7 +113,7 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
 {
        struct kvm_s390_interrupt_info *inti;
 
-       inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+       inti = kzalloc(sizeof(*inti), GFP_ATOMIC);
        if (!inti)
                return -ENOMEM;
        inti->type = KVM_S390_SIGP_STOP;
index 6409fd57eb049c837bd9693db08e835908121c99..3cc95dd0a3a6a1cb7bc133f0890786bf2324e4bf 100644 (file)
@@ -105,7 +105,7 @@ static int
 dcss_set_subcodes(void)
 {
 #ifdef CONFIG_64BIT
-       char *name = kmalloc(8 * sizeof(char), GFP_DMA);
+       char *name = kmalloc(8 * sizeof(char), GFP_KERNEL | GFP_DMA);
        unsigned long rx, ry;
        int rc;
 
@@ -252,12 +252,13 @@ dcss_diag_translate_rc (int vm_rc) {
 static int
 query_segment_type (struct dcss_segment *seg)
 {
-       struct qin64  *qin = kmalloc (sizeof(struct qin64), GFP_DMA);
-       struct qout64 *qout = kmalloc (sizeof(struct qout64), GFP_DMA);
-
-       int diag_cc, rc, i;
        unsigned long dummy, vmrc;
+       int diag_cc, rc, i;
+       struct qout64 *qout;
+       struct qin64 *qin;
 
+       qin = kmalloc(sizeof(*qin), GFP_KERNEL | GFP_DMA);
+       qout = kmalloc(sizeof(*qout), GFP_KERNEL | GFP_DMA);
        if ((qin == NULL) || (qout == NULL)) {
                rc = -ENOMEM;
                goto out_free;
@@ -286,7 +287,7 @@ query_segment_type (struct dcss_segment *seg)
           copy data for the new format. */
        if (segext_scode == DCSS_SEGEXT) {
                struct qout64_old *qout_old;
-               qout_old = kzalloc(sizeof(struct qout64_old), GFP_DMA);
+               qout_old = kzalloc(sizeof(*qout_old), GFP_KERNEL | GFP_DMA);
                if (qout_old == NULL) {
                        rc = -ENOMEM;
                        goto out_free;
@@ -407,11 +408,11 @@ segment_overlaps_others (struct dcss_segment *seg)
 static int
 __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long *end)
 {
-       struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment),
-                       GFP_DMA);
-       int rc, diag_cc;
        unsigned long start_addr, end_addr, dummy;
+       struct dcss_segment *seg;
+       int rc, diag_cc;
 
+       seg = kmalloc(sizeof(*seg), GFP_KERNEL | GFP_DMA);
        if (seg == NULL) {
                rc = -ENOMEM;
                goto out;
index c5ee4ce60b576d0e5155e940f9230a29cc622639..573fca1fbd9b699d7beff90a4d162af8a01652cd 100644 (file)
@@ -9,7 +9,7 @@ config SUPERH
        def_bool y
        select EMBEDDED
        select HAVE_CLK
-       select HAVE_IDE
+       select HAVE_IDE if HAS_IOPORT
        select HAVE_LMB
        select HAVE_OPROFILE
        select HAVE_GENERIC_DMA_COHERENT
@@ -174,6 +174,9 @@ config ARCH_HAS_DEFAULT_IDLE
 config ARCH_HAS_CPU_IDLE_WAIT
        def_bool y
 
+config NO_IOPORT
+       bool
+
 config IO_TRAPPED
        bool
 
@@ -776,6 +779,17 @@ config ENTRY_OFFSET
        default "0x00010000" if PAGE_SIZE_64KB
        default "0x00000000"
 
+config ROMIMAGE_MMCIF
+       bool "Include MMCIF loader in romImage (EXPERIMENTAL)"
+       depends on CPU_SUBTYPE_SH7724 && EXPERIMENTAL
+       help
+         Say Y here to include experimental MMCIF loading code in
+         romImage. With this enabled it is possible to write the romImage
+         kernel image to an MMC card and boot the kernel straight from
+         the reset vector. At reset the processor Mask ROM will load the
+         first part of the romImage which in turn loads the rest the kernel
+         image to RAM using the MMCIF hardware block.
+
 choice
        prompt "Kernel command line"
        optional
index 938e87d51482e991bd3fab373e8b1df67de070ce..07b35ca2f64449fee151ad7176d8d58a2795f7a7 100644 (file)
@@ -154,6 +154,7 @@ config SH_SDK7786
        bool "SDK7786"
        depends on CPU_SUBTYPE_SH7786
        select SYS_SUPPORTS_PCI
+       select NO_IOPORT if !PCI
        help
          Select SDK7786 if configuring for a Renesas Technology Europe
          SH7786-65nm board.
@@ -190,6 +191,7 @@ config SH_URQUELL
        depends on CPU_SUBTYPE_SH7786
        select ARCH_REQUIRE_GPIOLIB
        select SYS_SUPPORTS_PCI
+       select NO_IOPORT if !PCI
 
 config SH_MIGOR
        bool "Migo-R"
@@ -286,6 +288,7 @@ config SH_LBOX_RE2
 config SH_X3PROTO
        bool "SH-X3 Prototype board"
        depends on CPU_SUBTYPE_SHX3
+       select NO_IOPORT if !PCI
 
 config SH_MAGIC_PANEL_R2
        bool "Magic Panel R2"
index 57e37e2842082e84588718007fdd45f599b6c8a5..3a170bd3f3d06c1453b32e4ff544958859818ef2 100644 (file)
@@ -328,7 +328,7 @@ static struct soc_camera_platform_info camera_info = {
        .set_capture = camera_set_capture,
 };
 
-struct soc_camera_link camera_link = {
+static struct soc_camera_link camera_link = {
        .bus_id         = 0,
        .add_device     = ap325rxa_camera_add,
        .del_device     = ap325rxa_camera_del,
index 49714258732e57ff0be5da2f458f37f356f19ca5..1d7b495a7db485bf77952295117535d6ab9ce7df 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/sh_mobile_sdhi.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
 #include <linux/mtd/physmap.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/sh_msiof.h>
 #include <linux/spi/mmc_spi.h>
-#include <linux/mmc/host.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <video/sh_mobile_lcdc.h>
 #include <sound/sh_fsi.h>
 #include <media/sh_mobile_ceu.h>
@@ -139,7 +139,7 @@ static struct resource sh_eth_resources[] = {
        },
 };
 
-struct sh_eth_plat_data sh_eth_plat = {
+static struct sh_eth_plat_data sh_eth_plat = {
        .phy = 0x1f, /* SMSC LAN8700 */
        .edmac_endian = EDMAC_LITTLE_ENDIAN,
        .ether_link_active_low = 1
@@ -159,7 +159,7 @@ static struct platform_device sh_eth_device = {
 };
 
 /* USB0 host */
-void usb0_port_power(int port, int power)
+static void usb0_port_power(int port, int power)
 {
        gpio_set_value(GPIO_PTB4, power);
 }
@@ -195,7 +195,7 @@ static struct platform_device usb0_host_device = {
 };
 
 /* USB1 host/function */
-void usb1_port_power(int port, int power)
+static void usb1_port_power(int port, int power)
 {
        gpio_set_value(GPIO_PTB5, power);
 }
@@ -421,7 +421,7 @@ static int ts_init(void)
        return 0;
 }
 
-struct tsc2007_platform_data tsc2007_info = {
+static struct tsc2007_platform_data tsc2007_info = {
        .model                  = 2007,
        .x_plate_ohms           = 180,
        .get_pendown_state      = ts_get_pendown_state,
@@ -436,7 +436,7 @@ static struct i2c_board_info ts_i2c_clients = {
 };
 
 #ifdef CONFIG_MFD_SH_MOBILE_SDHI
-/* SHDI0 */
+/* SDHI0 */
 static void sdhi0_set_pwr(struct platform_device *pdev, int state)
 {
        gpio_set_value(GPIO_PTB6, state);
@@ -474,7 +474,8 @@ static struct platform_device sdhi0_device = {
        },
 };
 
-/* SHDI1 */
+#if !defined(CONFIG_MMC_SH_MMCIF)
+/* SDHI1 */
 static void sdhi1_set_pwr(struct platform_device *pdev, int state)
 {
        gpio_set_value(GPIO_PTB7, state);
@@ -511,6 +512,7 @@ static struct platform_device sdhi1_device = {
                .hwblk_id = HWBLK_SDHI1,
        },
 };
+#endif /* CONFIG_MMC_SH_MMCIF */
 
 #else
 
@@ -720,7 +722,7 @@ static struct clk fsimckb_clk = {
        .rate           = 0, /* unknown */
 };
 
-struct sh_fsi_platform_info fsi_info = {
+static struct sh_fsi_platform_info fsi_info = {
        .portb_flags = SH_FSI_BRS_INV |
                       SH_FSI_OUT_SLAVE_MODE |
                       SH_FSI_IN_SLAVE_MODE |
@@ -777,7 +779,7 @@ static struct platform_device irda_device = {
 #include <media/ak881x.h>
 #include <media/sh_vou.h>
 
-struct ak881x_pdata ak881x_pdata = {
+static struct ak881x_pdata ak881x_pdata = {
        .flags = AK881X_IF_MODE_SLAVE,
 };
 
@@ -786,7 +788,7 @@ static struct i2c_board_info ak8813 = {
        .platform_data = &ak881x_pdata,
 };
 
-struct sh_vou_pdata sh_vou_pdata = {
+static struct sh_vou_pdata sh_vou_pdata = {
        .bus_fmt        = SH_VOU_BUS_8BIT,
        .flags          = SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
        .board_info     = &ak8813,
@@ -819,6 +821,58 @@ static struct platform_device vou_device = {
        },
 };
 
+#if defined(CONFIG_MMC_SH_MMCIF)
+/* SH_MMCIF */
+static void mmcif_set_pwr(struct platform_device *pdev, int state)
+{
+       gpio_set_value(GPIO_PTB7, state);
+}
+
+static void mmcif_down_pwr(struct platform_device *pdev)
+{
+       gpio_set_value(GPIO_PTB7, 0);
+}
+
+static struct resource sh_mmcif_resources[] = {
+       [0] = {
+               .name   = "SH_MMCIF",
+               .start  = 0xA4CA0000,
+               .end    = 0xA4CA00FF,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* MMC2I */
+               .start  = 29,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               /* MMC3I */
+               .start  = 30,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct sh_mmcif_plat_data sh_mmcif_plat = {
+       .set_pwr        = mmcif_set_pwr,
+       .down_pwr       = mmcif_down_pwr,
+       .sup_pclk       = 0, /* SH7724: Max Pclk/2 */
+       .caps           = MMC_CAP_4_BIT_DATA |
+                         MMC_CAP_8_BIT_DATA |
+                         MMC_CAP_NEEDS_POLL,
+       .ocr            = MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static struct platform_device sh_mmcif_device = {
+       .name           = "sh_mmcif",
+       .id             = 0,
+       .dev            = {
+               .platform_data          = &sh_mmcif_plat,
+       },
+       .num_resources  = ARRAY_SIZE(sh_mmcif_resources),
+       .resource       = sh_mmcif_resources,
+};
+#endif
+
 static struct platform_device *ecovec_devices[] __initdata = {
        &heartbeat_device,
        &nor_flash_device,
@@ -831,7 +885,9 @@ static struct platform_device *ecovec_devices[] __initdata = {
        &keysc_device,
 #ifdef CONFIG_MFD_SH_MOBILE_SDHI
        &sdhi0_device,
+#if !defined(CONFIG_MMC_SH_MMCIF)
        &sdhi1_device,
+#endif
 #else
        &msiof0_device,
 #endif
@@ -841,6 +897,9 @@ static struct platform_device *ecovec_devices[] __initdata = {
        &fsi_device,
        &irda_device,
        &vou_device,
+#if defined(CONFIG_MMC_SH_MMCIF)
+       &sh_mmcif_device,
+#endif
 };
 
 #ifdef CONFIG_I2C
@@ -1134,6 +1193,7 @@ static int __init arch_setup(void)
        gpio_request(GPIO_PTB6, NULL);
        gpio_direction_output(GPIO_PTB6, 0);
 
+#if !defined(CONFIG_MMC_SH_MMCIF)
        /* enable SDHI1 on CN12 (needs DS2.6,7 set to ON,OFF) */
        gpio_request(GPIO_FN_SDHI1CD,  NULL);
        gpio_request(GPIO_FN_SDHI1WP,  NULL);
@@ -1148,6 +1208,7 @@ static int __init arch_setup(void)
 
        /* I/O buffer drive ability is high for SDHI1 */
        __raw_writew((__raw_readw(IODRIVEA) & ~0x3000) | 0x2000 , IODRIVEA);
+#endif /* CONFIG_MMC_SH_MMCIF */
 #else
        /* enable MSIOF0 on CN11 (needs DS2.4 set to OFF) */
        gpio_request(GPIO_FN_MSIOF0_TXD, NULL);
@@ -1223,6 +1284,25 @@ static int __init arch_setup(void)
        gpio_request(GPIO_PTU5, NULL);
        gpio_direction_output(GPIO_PTU5, 0);
 
+#if defined(CONFIG_MMC_SH_MMCIF)
+       /* enable MMCIF (needs DS2.6,7 set to OFF,ON) */
+       gpio_request(GPIO_FN_MMC_D7, NULL);
+       gpio_request(GPIO_FN_MMC_D6, NULL);
+       gpio_request(GPIO_FN_MMC_D5, NULL);
+       gpio_request(GPIO_FN_MMC_D4, NULL);
+       gpio_request(GPIO_FN_MMC_D3, NULL);
+       gpio_request(GPIO_FN_MMC_D2, NULL);
+       gpio_request(GPIO_FN_MMC_D1, NULL);
+       gpio_request(GPIO_FN_MMC_D0, NULL);
+       gpio_request(GPIO_FN_MMC_CLK, NULL);
+       gpio_request(GPIO_FN_MMC_CMD, NULL);
+       gpio_request(GPIO_PTB7, NULL);
+       gpio_direction_output(GPIO_PTB7, 0);
+
+       /* I/O buffer drive ability is high for MMCIF */
+       __raw_writew((__raw_readw(IODRIVEA) & ~0x3000) | 0x2000 , IODRIVEA);
+#endif
+
        /* enable I2C device */
        i2c_register_board_info(0, i2c0_devices,
                                ARRAY_SIZE(i2c0_devices));
index 87185de2044698724cb50b66e3770eb1359b2bf6..662debe4ead2fdaab217e7fc40ce19d32dcaf140 100644 (file)
@@ -181,7 +181,7 @@ static int migor_nand_flash_ready(struct mtd_info *mtd)
        return gpio_get_value(GPIO_PTA1); /* NAND_RBn */
 }
 
-struct platform_nand_data migor_nand_flash_data = {
+static struct platform_nand_data migor_nand_flash_data = {
        .chip = {
                .nr_chips = 1,
                .partitions = migor_nand_flash_partitions,
index f9b82546c2df9c1fc2216011244ba6edf67da1ee..552ebd9ba82b17f693c00e22251857cb503462a7 100644 (file)
@@ -283,7 +283,7 @@ static struct clk fsimcka_clk = {
 };
 
 /* change J20, J21, J22 pin to 1-2 connection to use slave mode */
-struct sh_fsi_platform_info fsi_info = {
+static struct sh_fsi_platform_info fsi_info = {
        .porta_flags = SH_FSI_BRS_INV |
                       SH_FSI_OUT_SLAVE_MODE |
                       SH_FSI_IN_SLAVE_MODE |
@@ -371,7 +371,7 @@ static struct resource sh_eth_resources[] = {
        },
 };
 
-struct sh_eth_plat_data sh_eth_plat = {
+static struct sh_eth_plat_data sh_eth_plat = {
        .phy = 0x1f, /* SMSC LAN8187 */
        .edmac_endian = EDMAC_LITTLE_ENDIAN,
 };
@@ -535,7 +535,7 @@ static struct platform_device irda_device = {
 #include <media/ak881x.h>
 #include <media/sh_vou.h>
 
-struct ak881x_pdata ak881x_pdata = {
+static struct ak881x_pdata ak881x_pdata = {
        .flags = AK881X_IF_MODE_SLAVE,
 };
 
@@ -545,7 +545,7 @@ static struct i2c_board_info ak8813 = {
        .platform_data = &ak881x_pdata,
 };
 
-struct sh_vou_pdata sh_vou_pdata = {
+static struct sh_vou_pdata sh_vou_pdata = {
        .bus_fmt        = SH_VOU_BUS_8BIT,
        .flags          = SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
        .board_info     = &ak8813,
index f02382ae5c48b1cd319a4cb1e755fa060f03cfdc..862d748082369a24eee471b493c4b07d3220ed36 100644 (file)
@@ -1,6 +1,6 @@
 SECTIONS
 {
-  .rodata.compressed : {
+  .rodata..compressed : {
        input_len = .;
        LONG(input_data_end - input_data) input_data = .;
        *(.data)
index f473a24a2d92e6e24b08ef26bdc1386f98c6335f..2216ee57f2516e14ff7c0017139dd01f1a83beb6 100644 (file)
@@ -1,16 +1,21 @@
 #
 # linux/arch/sh/boot/romimage/Makefile
 #
-# create an image suitable for burning to flash from zImage
+# create an romImage file suitable for burning to flash/mmc from zImage
 #
 
 targets                := vmlinux head.o zeropage.bin piggy.o
+load-y         := 0
 
-OBJECTS = $(obj)/head.o
-LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext 0 -e romstart \
+mmcif-load-$(CONFIG_CPU_SUBTYPE_SH7724)        := 0xe5200000 # ILRAM
+mmcif-obj-$(CONFIG_CPU_SUBTYPE_SH7724) := $(obj)/mmcif-sh7724.o
+load-$(CONFIG_ROMIMAGE_MMCIF)          := $(mmcif-load-y)
+obj-$(CONFIG_ROMIMAGE_MMCIF)           := $(mmcif-obj-y)
+
+LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(load-y) -e romstart \
                   -T $(obj)/../../kernel/vmlinux.lds
 
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
+$(obj)/vmlinux: $(obj)/head.o $(obj-y) $(obj)/piggy.o FORCE
        $(call if_changed,ld)
        @:
 
index 93e779a405eca3bf17fbc50e6e6cea41f8963d48..4671d1b82150f6aa077854ddd69b13b52738a8d7 100644 (file)
@@ -12,8 +12,40 @@ romstart:
        /* include board specific setup code */
 #include <mach/romimage.h>
 
+#ifdef CONFIG_ROMIMAGE_MMCIF
+       /* load the romImage to above the empty zero page */
+       mov.l   empty_zero_page_dst, r4
+       mov.l   empty_zero_page_dst_adj, r5
+       add     r5, r4
+       mov.l   bytes_to_load, r5
+       mov.l   loader_function, r7
+       jsr     @r7
+        mov    r4, r15
+
+       mov.l   empty_zero_page_dst, r4
+       mov.l   empty_zero_page_dst_adj, r5
+       add     r5, r4
+       mov.l   loaded_code_offs, r5
+       add     r5, r4
+       jmp     @r4
+        nop
+
+       .balign 4
+empty_zero_page_dst_adj:
+       .long   PAGE_SIZE
+bytes_to_load:
+       .long   end_data - romstart
+loader_function:
+       .long   mmcif_loader
+loaded_code_offs:
+       .long   loaded_code - romstart
+loaded_code:
+#endif /* CONFIG_ROMIMAGE_MMCIF */
+
        /* copy the empty_zero_page contents to where vmlinux expects it */
-       mova    empty_zero_page_src, r0
+       mova    extra_data_pos, r0
+       mov.l   extra_data_size, r1
+       add     r1, r0
        mov.l   empty_zero_page_dst, r1
        mov     #(PAGE_SHIFT - 4), r4
        mov     #1, r3
@@ -37,7 +69,9 @@ romstart:
        mov     #PAGE_SHIFT, r4
        mov     #1, r1
        shld    r4, r1
-       mova    empty_zero_page_src, r0
+       mova    extra_data_pos, r0
+       add     r1, r0
+       mov.l   extra_data_size, r1
        add     r1, r0
        jmp     @r0
         nop
@@ -45,4 +79,6 @@ romstart:
        .align 2
 empty_zero_page_dst:
        .long   _text
-empty_zero_page_src:
+extra_data_pos:
+extra_data_size:
+       .long   zero_page_pos - extra_data_pos
diff --git a/arch/sh/boot/romimage/mmcif-sh7724.c b/arch/sh/boot/romimage/mmcif-sh7724.c
new file mode 100644 (file)
index 0000000..14863d7
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * sh7724 MMCIF loader
+ *
+ * Copyright (C) 2010 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/mmc/sh_mmcif.h>
+#include <mach/romimage.h>
+
+#define MMCIF_BASE      (void __iomem *)0xa4ca0000
+
+#define MSTPCR2                0xa4150038
+#define PTWCR          0xa4050146
+#define PTXCR          0xa4050148
+#define PSELA          0xa405014e
+#define PSELE          0xa4050156
+#define HIZCRC         0xa405015c
+#define DRVCRA         0xa405018a
+
+enum { MMCIF_PROGRESS_ENTER, MMCIF_PROGRESS_INIT,
+       MMCIF_PROGRESS_LOAD, MMCIF_PROGRESS_DONE };
+
+/* SH7724 specific MMCIF loader
+ *
+ * loads the romImage from an MMC card starting from block 512
+ * use the following line to write the romImage to an MMC card
+ * # dd if=arch/sh/boot/romImage of=/dev/sdx bs=512 seek=512
+ */
+asmlinkage void mmcif_loader(unsigned char *buf, unsigned long no_bytes)
+{
+       mmcif_update_progress(MMCIF_PROGRESS_ENTER);
+
+       /* enable clock to the MMCIF hardware block */
+       __raw_writel(__raw_readl(MSTPCR2) & ~0x20000000, MSTPCR2);
+
+       /* setup pins D7-D0 */
+       __raw_writew(0x0000, PTWCR);
+
+       /* setup pins MMC_CLK, MMC_CMD */
+       __raw_writew(__raw_readw(PTXCR) & ~0x000f, PTXCR);
+
+       /* select D3-D0 pin function */
+       __raw_writew(__raw_readw(PSELA) & ~0x2000, PSELA);
+
+       /* select D7-D4 pin function */
+       __raw_writew(__raw_readw(PSELE) & ~0x3000, PSELE);
+
+       /* disable Hi-Z for the MMC pins */
+       __raw_writew(__raw_readw(HIZCRC) & ~0x0620, HIZCRC);
+
+       /* high drive capability for MMC pins */
+       __raw_writew(__raw_readw(DRVCRA) | 0x3000, DRVCRA);
+
+       mmcif_update_progress(MMCIF_PROGRESS_INIT);
+
+       /* setup MMCIF hardware */
+       sh_mmcif_boot_init(MMCIF_BASE);
+
+       mmcif_update_progress(MMCIF_PROGRESS_LOAD);
+
+       /* load kernel via MMCIF interface */
+       sh_mmcif_boot_slurp(MMCIF_BASE, buf, no_bytes);
+
+       /* disable clock to the MMCIF hardware block */
+       __raw_writel(__raw_readl(MSTPCR2) | 0x20000000, MSTPCR2);
+
+       mmcif_update_progress(MMCIF_PROGRESS_DONE);
+}
index 287c08f8b4bb9348666f5766d00467ad2b72fcc5..590394e2f5f2e48db6e500bf3fb0e6bebeab703f 100644 (file)
@@ -1,6 +1,8 @@
 SECTIONS
 {
   .text : {
+       zero_page_pos = .;
        *(.data)
+       end_data = .;
        }
 }
index 953af139e2300947ee9f76f1248c1f1267ac262c..1e9598d2bbf4832e69e43ba49eff659adcad46c8 100644 (file)
@@ -139,8 +139,6 @@ static void pcibios_fixup_device_resources(struct pci_dev *dev,
        for (i = 0; i < PCI_NUM_RESOURCES; i++) {
                if (!dev->resource[i].start)
                        continue;
-               if (dev->resource[i].flags & IORESOURCE_PCI_FIXED)
-                       continue;
                if (dev->resource[i].flags & IORESOURCE_IO)
                        offset = hose->io_offset;
                else if (dev->resource[i].flags & IORESOURCE_MEM)
index e461d67f03c3ff18f40151860121798e09471aea..ef9e555aafba5bad5247d0baeae0d256064b1620 100644 (file)
@@ -14,7 +14,7 @@
 
 #define L1_CACHE_BYTES         (1 << L1_CACHE_SHIFT)
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #ifndef __ASSEMBLY__
 struct cache_info {
index f689554e17c1ff81b40f3c0bf0b998357ef65319..b237d525d5926d0daeafc577ab04525447facac8 100644 (file)
@@ -39,6 +39,8 @@
 #include <asm/io_generic.h>
 #include <asm/io_trapped.h>
 
+#ifdef CONFIG_HAS_IOPORT
+
 #define inb(p)                 sh_mv.mv_inb((p))
 #define inw(p)                 sh_mv.mv_inw((p))
 #define inl(p)                 sh_mv.mv_inl((p))
@@ -60,6 +62,8 @@
 #define outsw(p,b,c)           sh_mv.mv_outsw((p), (b), (c))
 #define outsl(p,b,c)           sh_mv.mv_outsl((p), (b), (c))
 
+#endif
+
 #define __raw_writeb(v,a)      (__chk_io_ptr(a), *(volatile u8  __force *)(a) = (v))
 #define __raw_writew(v,a)      (__chk_io_ptr(a), *(volatile u16 __force *)(a) = (v))
 #define __raw_writel(v,a)      (__chk_io_ptr(a), *(volatile u32 __force *)(a) = (v))
@@ -240,6 +244,8 @@ __BUILD_MEMORY_STRING(q, u64)
 
 #define IO_SPACE_LIMIT 0xffffffff
 
+#ifdef CONFIG_HAS_IOPORT
+
 /*
  * This function provides a method for the generic case where a
  * board-specific ioport_map simply needs to return the port + some
@@ -255,6 +261,8 @@ static inline void __set_io_port_base(unsigned long pbase)
 
 #define __ioport_map(p, n) sh_mv.mv_ioport_map((p), (n))
 
+#endif
+
 /* We really want to try and get these to memcpy etc */
 void memcpy_fromio(void *, const volatile void __iomem *, unsigned long);
 void memcpy_toio(volatile void __iomem *, const void *, unsigned long);
index bc0218cb72e13992c97602bdc9e2679cdcdea323..a0b0cf79cf8a608b9c0fa351f7e1a7eb17e51b39 100644 (file)
@@ -19,6 +19,10 @@ struct sh_machine_vector {
        const char *mv_name;
        int mv_nr_irqs;
 
+       int (*mv_irq_demux)(int irq);
+       void (*mv_init_irq)(void);
+
+#ifdef CONFIG_HAS_IOPORT
        u8 (*mv_inb)(unsigned long);
        u16 (*mv_inw)(unsigned long);
        u32 (*mv_inl)(unsigned long);
@@ -40,12 +44,9 @@ struct sh_machine_vector {
        void (*mv_outsw)(unsigned long, const void *src, unsigned long count);
        void (*mv_outsl)(unsigned long, const void *src, unsigned long count);
 
-       int (*mv_irq_demux)(int irq);
-
-       void (*mv_init_irq)(void);
-
        void __iomem *(*mv_ioport_map)(unsigned long port, unsigned int size);
        void (*mv_ioport_unmap)(void __iomem *);
+#endif
 
        int (*mv_clk_init)(void);
        int (*mv_mode_pins)(void);
index fbbf550cc529c10d3ebbb8aa010de963d3a842fc..4c27b68789b3fd02a89fea5c6ae42fb0a347e0d5 100644 (file)
@@ -9,6 +9,7 @@
  * MD3: BSC - Area0 Bus Width (16/32-bit) [CS0BCR.9,10]
  * MD5: BSC - Endian Mode (L: Big, H: Little) [CMNCR.3]
  * MD8: Test Mode
+ * BOOT: FBR - Boot Mode (L: MMCIF, H: Area0)
  */
 
 /* Pin Function Controller:
index 267e24112d8233585f47e02aa1f7d655f33c89b4..08fb42269ecd1c836c29d7b85b993a4796764dcf 100644 (file)
@@ -1 +1,11 @@
+#ifdef __ASSEMBLY__
+
 /* do nothing here by default */
+
+#else /* __ASSEMBLY__ */
+
+extern inline void mmcif_update_progress(int nr)
+{
+}
+
+#endif /* __ASSEMBLY__ */
index 1c8787ecb1c117b014aeccc9296ca64bcd932fb4..1dcf5e6c8d83239966df26af919fa5fa2300bccb 100644 (file)
@@ -1,3 +1,5 @@
+#ifdef __ASSEMBLY__
+
 /* EcoVec board specific boot code:
  * converts the "partner-jet-script.txt" script into assembly
  * the assembly code is the first code to be executed in the romImage
        .align 2
 1 :    .long 0xa8000000
 2 :
+
+#else /* __ASSEMBLY__ */
+
+/* Ecovec board specific information:
+ *
+ * Set the following to enable MMCIF boot from the MMC card in CN12:
+ *
+ * DS1.5 = OFF (SH BOOT pin set to L)
+ * DS2.6 = OFF (Select MMCIF on CN12 instead of SDHI1)
+ * DS2.7 = ON  (Select MMCIF on CN12 instead of SDHI1)
+ *
+ */
+#define HIZCRA         0xa4050158
+#define PGDR           0xa405012c
+
+extern inline void mmcif_update_progress(int nr)
+{
+       /* disable Hi-Z for LED pins */
+       __raw_writew(__raw_readw(HIZCRA) & ~(1 << 1), HIZCRA);
+
+       /* update progress on LED4, LED5, LED6 and LED7 */
+       __raw_writeb(1 << (nr - 1), PGDR);
+}
+
+#endif /* __ASSEMBLY__ */
index a110823f2bde78d8966d5aefd77ea688bfb7b447..976256a323f2c4a85e1bdd9dbd18b1209f5e5ba0 100644 (file)
@@ -1,3 +1,5 @@
+#ifdef __ASSEMBLY__
+
 /* kfr2r09 board specific boot code:
  * converts the "partner-jet-script.txt" script into assembly
  * the assembly code is the first code to be executed in the romImage
        .align 2
 1:     .long 0xa8000000
 2:
+
+#else /* __ASSEMBLY__ */
+
+extern inline void mmcif_update_progress(int nr)
+{
+}
+
+#endif /* __ASSEMBLY__ */
index 650b92f00ee56411fbaabe648db36c5d91c66e17..e25f3c69525d4eeb4aaed3fc9a5d724efb797124 100644 (file)
@@ -12,7 +12,7 @@ endif
 CFLAGS_REMOVE_return_address.o = -pg
 
 obj-y  := clkdev.o debugtraps.o dma-nommu.o dumpstack.o                \
-          idle.o io.o io_generic.o irq.o                               \
+          idle.o io.o irq.o                                            \
           irq_$(BITS).o machvec.o nmi_debug.o process.o                \
           process_$(BITS).o ptrace_$(BITS).o                           \
           reboot.o return_address.o                                    \
@@ -39,6 +39,7 @@ obj-$(CONFIG_DUMP_CODE)               += disassemble.o
 obj-$(CONFIG_HIBERNATION)      += swsusp.o
 obj-$(CONFIG_DWARF_UNWINDER)   += dwarf.o
 obj-$(CONFIG_PERF_EVENTS)      += perf_event.o perf_callchain.o
+obj-$(CONFIG_HAS_IOPORT)       += io_generic.o
 
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)               += hw_breakpoint.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += localtimer.o
index 886d7d83ace38912aa4966da50159d43686b0fde..49c09c7d5b77ce76b3351bf2174251756c7b9b41 100644 (file)
@@ -49,6 +49,8 @@ static DEFINE_SPINLOCK(dwarf_fde_lock);
 
 static struct dwarf_cie *cached_cie;
 
+static unsigned int dwarf_unwinder_ready;
+
 /**
  *     dwarf_frame_alloc_reg - allocate memory for a DWARF register
  *     @frame: the DWARF frame whose list of registers we insert on
@@ -581,6 +583,13 @@ struct dwarf_frame *dwarf_unwind_stack(unsigned long pc,
        struct dwarf_reg *reg;
        unsigned long addr;
 
+       /*
+        * If we've been called in to before initialization has
+        * completed, bail out immediately.
+        */
+       if (!dwarf_unwinder_ready)
+               return NULL;
+
        /*
         * If we're starting at the top of the stack we need get the
         * contents of a physical register to get the CFA in order to
@@ -1167,7 +1176,7 @@ void module_dwarf_cleanup(struct module *mod)
  */
 static int __init dwarf_unwinder_init(void)
 {
-       int err;
+       int err = -ENOMEM;
 
        dwarf_frame_cachep = kmem_cache_create("dwarf_frames",
                        sizeof(struct dwarf_frame), 0,
@@ -1181,11 +1190,15 @@ static int __init dwarf_unwinder_init(void)
                                          mempool_alloc_slab,
                                          mempool_free_slab,
                                          dwarf_frame_cachep);
+       if (!dwarf_frame_pool)
+               goto out;
 
        dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ,
                                         mempool_alloc_slab,
                                         mempool_free_slab,
                                         dwarf_reg_cachep);
+       if (!dwarf_reg_pool)
+               goto out;
 
        err = dwarf_parse_section(__start_eh_frame, __stop_eh_frame, NULL);
        if (err)
@@ -1195,11 +1208,13 @@ static int __init dwarf_unwinder_init(void)
        if (err)
                goto out;
 
+       dwarf_unwinder_ready = 1;
+
        return 0;
 
 out:
        printk(KERN_ERR "Failed to initialise DWARF unwinder: %d\n", err);
        dwarf_unwinder_cleanup();
-       return -EINVAL;
+       return err;
 }
 early_initcall(dwarf_unwinder_init);
index 4770c241c6790192a4954d2274de144b8da5938a..5c51b794ba2a8a7591546f79a18271d73e33e771 100644 (file)
@@ -112,25 +112,3 @@ void memset_io(volatile void __iomem *dst, int c, unsigned long count)
         }
 }
 EXPORT_SYMBOL(memset_io);
-
-#ifndef CONFIG_GENERIC_IOMAP
-
-void __iomem *ioport_map(unsigned long port, unsigned int nr)
-{
-       void __iomem *ret;
-
-       ret = __ioport_map_trapped(port, nr);
-       if (ret)
-               return ret;
-
-       return __ioport_map(port, nr);
-}
-EXPORT_SYMBOL(ioport_map);
-
-void ioport_unmap(void __iomem *addr)
-{
-       sh_mv.mv_ioport_unmap(addr);
-}
-EXPORT_SYMBOL(ioport_unmap);
-
-#endif /* CONFIG_GENERIC_IOMAP */
index e1e1dbd195579e5cacc7a5437020a75bcc695757..447d78f666f90ef2f34430185a1d10ae8ef9ddb4 100644 (file)
@@ -158,3 +158,23 @@ void __iomem *generic_ioport_map(unsigned long addr, unsigned int size)
 void generic_ioport_unmap(void __iomem *addr)
 {
 }
+
+#ifndef CONFIG_GENERIC_IOMAP
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+       void __iomem *ret;
+
+       ret = __ioport_map_trapped(port, nr);
+       if (ret)
+               return ret;
+
+       return __ioport_map(port, nr);
+}
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+       sh_mv.mv_ioport_unmap(addr);
+}
+EXPORT_SYMBOL(ioport_unmap);
+#endif /* CONFIG_GENERIC_IOMAP */
index 4a8bb4eeb8ad7ffc5dee5a312712fafda419028c..2947d2bd12919e5d19117839a9d180ff918a93f3 100644 (file)
@@ -91,10 +91,14 @@ int register_trapped_io(struct trapped_io *tiop)
        tiop->magic = IO_TRAPPED_MAGIC;
        INIT_LIST_HEAD(&tiop->list);
        spin_lock_irq(&trapped_lock);
+#ifdef CONFIG_HAS_IOPORT
        if (flags & IORESOURCE_IO)
                list_add(&tiop->list, &trapped_io);
+#endif
+#ifdef CONFIG_HAS_IOMEM
        if (flags & IORESOURCE_MEM)
                list_add(&tiop->list, &trapped_mem);
+#endif
        spin_unlock_irq(&trapped_lock);
 
        return 0;
index 85cfaf916fdc027d4206f1fc3976cc40fc889c9c..9f9bb63616adf6067151b1d85241044469cc2627 100644 (file)
@@ -118,6 +118,14 @@ void __init sh_mv_setup(void)
                sh_mv.mv_##elem = generic_##elem; \
 } while (0)
 
+#ifdef CONFIG_HAS_IOPORT
+
+#ifdef P2SEG
+       __set_io_port_base(P2SEG);
+#else
+       __set_io_port_base(0);
+#endif
+
        mv_set(inb);    mv_set(inw);    mv_set(inl);
        mv_set(outb);   mv_set(outw);   mv_set(outl);
 
@@ -129,16 +137,13 @@ void __init sh_mv_setup(void)
 
        mv_set(ioport_map);
        mv_set(ioport_unmap);
+
+#endif
+
        mv_set(irq_demux);
        mv_set(mode_pins);
        mv_set(mem_init);
 
        if (!sh_mv.mv_nr_irqs)
                sh_mv.mv_nr_irqs = NR_IRQS;
-
-#ifdef P2SEG
-       __set_io_port_base(P2SEG);
-#else
-       __set_io_port_base(0);
-#endif
 }
index cbf1dd5372b2d223f399ab884fd46bfbd83246d1..5124aeb28c3f333d9b7ff7755d8f01e738a044d1 100644 (file)
@@ -24,6 +24,8 @@ void *return_address(unsigned int depth)
                struct dwarf_frame *tmp;
 
                tmp = dwarf_unwind_stack(ra, frame);
+               if (!tmp)
+                       return NULL;
 
                if (frame)
                        dwarf_free_frame(frame);
index 18623ba751b32e3863094bae05bcf44d58141f4b..6379091a164764040c57fce64b9a9dae521bff41 100644 (file)
@@ -770,7 +770,7 @@ static void __init pmb_resize(void)
                spin_unlock_irqrestore(&pmbe->lock, flags);
        }
 
-       read_lock(&pmb_rwlock);
+       read_unlock(&pmb_rwlock);
 }
 #endif
 
index bbf91b9c3d39fc0bc770eed6fb629001a6f7c630..e7f2940bd270f5ab481e513880019c3b34a7bb2a 100644 (file)
@@ -325,7 +325,7 @@ main1:
                (*rr)->next = NULL;
        }
        printf("! Generated by btfixupprep. Do not edit.\n\n");
-       printf("\t.section\t\".data.init\",#alloc,#write\n\t.align\t4\n\n");
+       printf("\t.section\t\".data..init\",#alloc,#write\n\t.align\t4\n\n");
        printf("\t.global\t___btfixup_start\n___btfixup_start:\n\n");
        for (i = 0; i < last; i++) {
                f = array + i;
index 78b07009f60a9d52c8042fc1c9124fef9d6a2f16..0588b8c7faa26b5eb596a1c52a1bcbf77a53bc92 100644 (file)
@@ -21,7 +21,7 @@
 
 #define SMP_CACHE_BYTES (1 << SMP_CACHE_BYTES_SHIFT)
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #ifdef CONFIG_SPARC32
 #include <asm/asi.h>
diff --git a/arch/um/include/asm/arch_hweight.h b/arch/um/include/asm/arch_hweight.h
new file mode 100644 (file)
index 0000000..c656cf4
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_UM_HWEIGHT_H
+#define _ASM_UM_HWEIGHT_H
+
+#include <asm-generic/bitops/arch_hweight.h>
+
+#endif
index 7fcad58e216db26022eb32bd581134a67849af8b..69268014dd8e966860f7faa323b394961b6f6428 100644 (file)
@@ -94,7 +94,7 @@ SECTIONS
   .data           : {
     INIT_TASK_DATA(KERNEL_STACK_SIZE)
     . = ALIGN(KERNEL_STACK_SIZE);
-    *(.data.init_irqstack)
+    *(.data..init_irqstack)
     DATA_DATA
     *(.data.* .gnu.linkonce.d.*)
     SORT(CONSTRUCTORS)
index 8aa77b61a5ff09458786c249b1419c8b9dac68ef..ddc9698b66edc71d5da6508c8c40bb523df84760 100644 (file)
@@ -34,5 +34,5 @@ union thread_union init_thread_union __init_task_data =
        { INIT_THREAD_INFO(init_task) };
 
 union thread_union cpu0_irqstack
-       __attribute__((__section__(".data.init_irqstack"))) =
+       __attribute__((__section__(".data..init_irqstack"))) =
                { INIT_THREAD_INFO(init_task) };
index e22c96993db3b07545e107adb57f2ef1d8ddb608..696634214dc65551557ab88535b40557fed4eb7c 100644 (file)
@@ -81,7 +81,7 @@ static int do_op_one_page(unsigned long addr, int len, int is_write,
 
        current->thread.fault_catcher = NULL;
 
-       kunmap_atomic(page, KM_UML_USERCOPY);
+       kunmap_atomic((void *)addr, KM_UML_USERCOPY);
 
        return n;
 }
index e7a6cca667aa5c0a6ec0a8df5392976d8d97aea9..ec63785506714f8059c9c7a31cf44d4875466698 100644 (file)
@@ -50,7 +50,7 @@ SECTIONS
   {
     INIT_TASK_DATA(KERNEL_STACK_SIZE)
     . = ALIGN(KERNEL_STACK_SIZE);
-    *(.data.init_irqstack)
+    *(.data..init_irqstack)
     DATA_DATA
     *(.gnu.linkonce.d*)
     CONSTRUCTORS
index 93a11d7edfa0505a7acfd9bd99a0266aec97f933..e696144d2be3ddb23ba952fdd17ea8fdf923036c 100644 (file)
@@ -10,6 +10,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <string.h>
+#include <sys/stat.h>
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "init.h"
diff --git a/arch/x86/.gitignore b/arch/x86/.gitignore
new file mode 100644 (file)
index 0000000..0280790
--- /dev/null
@@ -0,0 +1,3 @@
+boot/compressed/vmlinux
+tools/test_get_len
+
index bcbd36c414321257217cfefdc1520f1ba924d273..5c228129d175779976b1985f8af86c5b9d80a668 100644 (file)
@@ -77,7 +77,7 @@ int main(int argc, char *argv[])
        offs += 32*1024 + 18;   /* Add 32K + 18 bytes slack */
        offs = (offs+4095) & ~4095; /* Round to a 4K boundary */
 
-       printf(".section \".rodata.compressed\",\"a\",@progbits\n");
+       printf(".section \".rodata..compressed\",\"a\",@progbits\n");
        printf(".globl z_input_len\n");
        printf("z_input_len = %lu\n", ilen);
        printf(".globl z_output_len\n");
index a6f1a59a5b0cc491e772eb04d2d1570d9e32bf85..5ddabceee12408d55f22b6412bbd4617dc684c55 100644 (file)
@@ -26,8 +26,8 @@ SECTIONS
                HEAD_TEXT
                _ehead = . ;
        }
-       .rodata.compressed : {
-               *(.rodata.compressed)
+       .rodata..compressed : {
+               *(.rodata..compressed)
        }
        .text : {
                _text = .;      /* Text */
index ed7aeff786b277d01b281a47c418eb5c988ea249..45bc9402aa497f7c7151a7ce3e0b419ab9454301 100644 (file)
@@ -41,13 +41,12 @@ static __videocard video_vga;
 static u8 vga_set_basic_mode(void)
 {
        struct biosregs ireg, oreg;
-       u16 ax;
        u8 mode;
 
        initregs(&ireg);
 
        /* Query current mode */
-       ax = 0x0f00;
+       ireg.ax = 0x0f00;
        intcall(0x10, &ireg, &oreg);
        mode = oreg.al;
 
index 2f9047cfaacafe0bfcf90e09d514fff0e948224f..48f99f15452e7d111e8bad21a4830d21231071cc 100644 (file)
@@ -7,7 +7,7 @@
 #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT)
 #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #define INTERNODE_CACHE_SHIFT CONFIG_X86_INTERNODE_CACHE_SHIFT
 #define INTERNODE_CACHE_BYTES (1 << INTERNODE_CACHE_SHIFT)
index 63cb4096c3dc998efba7e160f6804c0b6d80c309..9cb2edb87c2f718780fb00cc61ebc1bfa5ad0228 100644 (file)
@@ -183,7 +183,7 @@ struct mp_ioapic_gsi{
        u32 gsi_end;
 };
 extern struct mp_ioapic_gsi  mp_gsi_routing[];
-extern u32 gsi_end;
+extern u32 gsi_top;
 int mp_find_ioapic(u32 gsi);
 int mp_find_ioapic_pin(int ioapic, u32 gsi);
 void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
@@ -197,7 +197,7 @@ static const int timer_through_8259 = 0;
 static inline void ioapic_init_mappings(void)  { }
 static inline void ioapic_insert_resources(void) { }
 static inline void probe_nr_irqs_gsi(void)     { }
-#define gsi_end (NR_IRQS_LEGACY - 1)
+#define gsi_top (NR_IRQS_LEGACY)
 static inline int mp_find_ioapic(u32 gsi) { return 0; }
 
 struct io_apic_irq_attr;
index b49d8ca228f6ffe743e19d0423c676e62b1d29df..8c7ae4318629445f16b588e9535b0dc2a105836c 100644 (file)
 #define MSR_AMD64_PATCH_LOADER         0xc0010020
 #define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
 #define MSR_AMD64_OSVW_STATUS          0xc0010141
+#define MSR_AMD64_DC_CFG               0xc0011022
 #define MSR_AMD64_IBSFETCHCTL          0xc0011030
 #define MSR_AMD64_IBSFETCHLINAD                0xc0011031
 #define MSR_AMD64_IBSFETCHPHYSAD       0xc0011032
index 8d8797eae5d704e238d764b4b4d1e7254c2ecc62..cd2a31dc5fb8e4a956c8c34125534540d51b08f4 100644 (file)
@@ -53,6 +53,8 @@ extern int pcibios_last_bus;
 extern struct pci_bus *pci_root_bus;
 extern struct pci_ops pci_root_ops;
 
+void pcibios_scan_specific_bus(int busn);
+
 /* pci-irq.c */
 
 struct irq_info {
index 0797e748d2801839fecf63915a8d2d857347884c..cd28f9ad910d1a8bc83fa0c4c6d1f1ca907e042f 100644 (file)
@@ -77,6 +77,7 @@ do {                                                  \
        if (0) {                                        \
                pto_T__ pto_tmp__;                      \
                pto_tmp__ = (val);                      \
+               (void)pto_tmp__;                        \
        }                                               \
        switch (sizeof(var)) {                          \
        case 1:                                         \
@@ -115,6 +116,7 @@ do {                                                                        \
        if (0) {                                                        \
                pao_T__ pao_tmp__;                                      \
                pao_tmp__ = (val);                                      \
+               (void)pao_tmp__;                                        \
        }                                                               \
        switch (sizeof(var)) {                                          \
        case 1:                                                         \
index 5e67c15323145753d29894eb43c4c29f0343f38e..ed5903be26fe6a04b101a069ecbaeea497a757f6 100644 (file)
@@ -26,7 +26,7 @@
  */
 #define VMALLOC_OFFSET (8 * 1024 * 1024)
 
-#ifndef __ASSEMBLER__
+#ifndef __ASSEMBLY__
 extern bool __vmalloc_start_set; /* set once high_memory is set */
 #endif
 
index 48dcfa62ea07eb5985ef61c526ed767da3795283..fd921c3a68414e341fe8fffa8b1df1326eba2ba7 100644 (file)
@@ -15,6 +15,8 @@ static inline int arch_prepare_suspend(void) { return 0; }
 struct saved_context {
        u16 es, fs, gs, ss;
        unsigned long cr0, cr2, cr3, cr4;
+       u64 misc_enable;
+       bool misc_enable_saved;
        struct desc_ptr gdt;
        struct desc_ptr idt;
        u16 ldt;
index 06284f42b7599a8f46669fc3e4f6c9d8bbea7eb7..8d942afae681bec8fe2c47a9bf57955dbc4317b0 100644 (file)
@@ -27,6 +27,8 @@ struct saved_context {
        u16 ds, es, fs, gs, ss;
        unsigned long gs_base, gs_kernel_base, fs_base;
        unsigned long cr0, cr2, cr3, cr4, cr8;
+       u64 misc_enable;
+       bool misc_enable_saved;
        unsigned long efer;
        u16 gdt_pad;
        u16 gdt_limit;
index b8fe48ee2ed971d648fa4ad940a210ddfc9fb90c..e7f4d33c55edbb80b8ec52d9793a45d3c8854519 100644 (file)
@@ -451,7 +451,7 @@ void stop_this_cpu(void *dummy);
  *
  * (Could use an alternative three way for this if there was one.)
  */
-static inline void rdtsc_barrier(void)
+static __always_inline void rdtsc_barrier(void)
 {
        alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
        alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
index 60cc4058ed5feb9c05dcf7917593c099d21df4df..c05872aa3ce08ed39648c0eb0b4bd2bde281b362 100644 (file)
@@ -118,7 +118,7 @@ static unsigned int gsi_to_irq(unsigned int gsi)
        if (gsi >= NR_IRQS_LEGACY)
                irq = gsi;
        else
-               irq = gsi_end + 1 + gsi;
+               irq = gsi_top + gsi;
 
        return irq;
 }
@@ -129,10 +129,10 @@ static u32 irq_to_gsi(int irq)
 
        if (irq < NR_IRQS_LEGACY)
                gsi = isa_irq_to_gsi[irq];
-       else if (irq <= gsi_end)
+       else if (irq < gsi_top)
                gsi = irq;
-       else if (irq <= (gsi_end + NR_IRQS_LEGACY))
-               gsi = irq - gsi_end;
+       else if (irq < (gsi_top + NR_IRQS_LEGACY))
+               gsi = irq - gsi_top;
        else
                gsi = 0xffffffff;
 
index 8ded418b05939f1fc2f9ef6512fd21281bd2b10a..13ab720573e3e31e317ac52f977e168401552f17 100644 (file)
@@ -1,4 +1,4 @@
-       .section .text.page_aligned
+       .section .text..page_aligned
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/page_types.h>
index fa5a1474cd182db250e189cfc8b262683f2585ba..0d20286d78c6f6b6b4307ef35dc5001cccc480a9 100644 (file)
@@ -1487,6 +1487,7 @@ static int __attach_device(struct device *dev,
                           struct protection_domain *domain)
 {
        struct iommu_dev_data *dev_data, *alias_data;
+       int ret;
 
        dev_data   = get_dev_data(dev);
        alias_data = get_dev_data(dev_data->alias);
@@ -1498,13 +1499,14 @@ static int __attach_device(struct device *dev,
        spin_lock(&domain->lock);
 
        /* Some sanity checks */
+       ret = -EBUSY;
        if (alias_data->domain != NULL &&
            alias_data->domain != domain)
-               return -EBUSY;
+               goto out_unlock;
 
        if (dev_data->domain != NULL &&
            dev_data->domain != domain)
-               return -EBUSY;
+               goto out_unlock;
 
        /* Do real assignment */
        if (dev_data->alias != dev) {
@@ -1520,10 +1522,14 @@ static int __attach_device(struct device *dev,
 
        atomic_inc(&dev_data->bind);
 
+       ret = 0;
+
+out_unlock:
+
        /* ready */
        spin_unlock(&domain->lock);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -2324,10 +2330,6 @@ int __init amd_iommu_init_dma_ops(void)
 
        iommu_detected = 1;
        swiotlb = 0;
-#ifdef CONFIG_GART_IOMMU
-       gart_iommu_aperture_disabled = 1;
-       gart_iommu_aperture = 0;
-#endif
 
        /* Make the driver finally visible to the drivers */
        dma_ops = &amd_iommu_dma_ops;
index 3bacb4d0844c1e6b7794b6a23013dcbf77f3694e..3cc63e2b8dd4c4acc4ee7f77c3ad432d97beb169 100644 (file)
@@ -287,8 +287,12 @@ static u8 * __init iommu_map_mmio_space(u64 address)
 {
        u8 *ret;
 
-       if (!request_mem_region(address, MMIO_REGION_LENGTH, "amd_iommu"))
+       if (!request_mem_region(address, MMIO_REGION_LENGTH, "amd_iommu")) {
+               pr_err("AMD-Vi: Can not reserve memory region %llx for mmio\n",
+                       address);
+               pr_err("AMD-Vi: This is a BIOS bug. Please contact your hardware vendor\n");
                return NULL;
+       }
 
        ret = ioremap_nocache(address, MMIO_REGION_LENGTH);
        if (ret != NULL)
@@ -1314,7 +1318,7 @@ static int __init amd_iommu_init(void)
                ret = amd_iommu_init_dma_ops();
 
        if (ret)
-               goto free;
+               goto free_disable;
 
        amd_iommu_init_api();
 
@@ -1332,9 +1336,10 @@ static int __init amd_iommu_init(void)
 out:
        return ret;
 
-free:
+free_disable:
        disable_iommus();
 
+free:
        amd_iommu_uninit_devices();
 
        free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,
@@ -1353,6 +1358,15 @@ free:
 
        free_unity_maps();
 
+#ifdef CONFIG_GART_IOMMU
+       /*
+        * We failed to initialize the AMD IOMMU - try fallback to GART
+        * if possible.
+        */
+       gart_iommu_init();
+
+#endif
+
        goto out;
 }
 
index 33f3563a2a52a8b40cc2a07d8a60a03a583457a7..e41ed24ab26d5b51490ffa8f9a7c58a653b829d8 100644 (file)
@@ -89,8 +89,8 @@ int nr_ioapics;
 /* IO APIC gsi routing info */
 struct mp_ioapic_gsi  mp_gsi_routing[MAX_IO_APICS];
 
-/* The last gsi number used */
-u32 gsi_end;
+/* The one past the highest gsi number used */
+u32 gsi_top;
 
 /* MP IRQ source entries */
 struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
@@ -1035,7 +1035,7 @@ static int pin_2_irq(int idx, int apic, int pin)
                if (gsi >= NR_IRQS_LEGACY)
                        irq = gsi;
                else
-                       irq = gsi_end + 1 + gsi;
+                       irq = gsi_top + gsi;
        }
 
 #ifdef CONFIG_X86_32
@@ -3853,7 +3853,7 @@ void __init probe_nr_irqs_gsi(void)
 {
        int nr;
 
-       nr = gsi_end + 1 + NR_IRQS_LEGACY;
+       nr = gsi_top + NR_IRQS_LEGACY;
        if (nr > nr_irqs_gsi)
                nr_irqs_gsi = nr;
 
@@ -4294,8 +4294,8 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
         */
        nr_ioapic_registers[idx] = entries;
 
-       if (mp_gsi_routing[idx].gsi_end > gsi_end)
-               gsi_end = mp_gsi_routing[idx].gsi_end;
+       if (mp_gsi_routing[idx].gsi_end >= gsi_top)
+               gsi_top = mp_gsi_routing[idx].gsi_end + 1;
 
        printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
               "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
index 707165dbc20343310147dcd483605b7bfde456f0..18cc4256225081077161c027a9bb1bae1013ab44 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/debugfs.h>
+#include <linux/edac_mce.h>
 
 #include <asm/processor.h>
 #include <asm/hw_irq.h>
@@ -168,6 +169,15 @@ void mce_log(struct mce *mce)
        for (;;) {
                entry = rcu_dereference_check_mce(mcelog.next);
                for (;;) {
+                       /*
+                        * If edac_mce is enabled, it will check the error type
+                        * and will process it, if it is a known error.
+                        * Otherwise, the error will be sent through mcelog
+                        * interface
+                        */
+                       if (edac_mce_parse(mce))
+                               return;
+
                        /*
                         * When the buffer fills up discard new entries.
                         * Assume that the earlier errors are the more
index 7bca3c6a02fb186ebd039ff495f05fd051f32b6e..0d6fc71bedb152802401b49eb801696cb5ee460d 100644 (file)
@@ -729,7 +729,7 @@ static int __init e820_mark_nvs_memory(void)
                struct e820entry *ei = &e820.map[i];
 
                if (ei->type == E820_NVS)
-                       hibernate_nvs_register(ei->addr, ei->size);
+                       suspend_nvs_register(ei->addr, ei->size);
        }
 
        return 0;
index 3a54dcb9cd0e6c82b8b9231e88afd7305be6e5da..43e9ccf449471286fd0013ae1bc28ce83778b9a6 100644 (file)
@@ -34,7 +34,7 @@ EXPORT_SYMBOL(init_task);
 /*
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
  * no more per-task TSS's. The TSS size is kept cacheline-aligned
- * so they are allowed to end up in the .data.cacheline_aligned
+ * so they are allowed to end up in the .data..cacheline_aligned
  * section. Since TSS's are completely CPU-local, we want them
  * on exact cacheline boundaries, to eliminate cacheline ping-pong.
  */
index 5ae5d2426edfd0f74e3d9a4235bd143b5c9f5768..d86dbf7e54be4384aae5c2c886e3e690780f40f3 100644 (file)
@@ -123,7 +123,7 @@ static void __init MP_ioapic_info(struct mpc_ioapic *m)
        printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
               m->apicid, m->apicver, m->apicaddr);
 
-       mp_register_ioapic(m->apicid, m->apicaddr, gsi_end + 1);
+       mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
 }
 
 static void print_MP_intsrc_info(struct mpc_intsrc *m)
index fb99f7edb3418322653f6c97ce480083191860a8..0b96b5589f089b4aa60b4d5c51e1300efd07226e 100644 (file)
@@ -103,11 +103,16 @@ int use_calgary __read_mostly = 0;
 #define PMR_SOFTSTOPFAULT      0x40000000
 #define PMR_HARDSTOP           0x20000000
 
-#define MAX_NUM_OF_PHBS                8 /* how many PHBs in total? */
-#define MAX_NUM_CHASSIS                8 /* max number of chassis */
-/* MAX_PHB_BUS_NUM is the maximal possible dev->bus->number */
-#define MAX_PHB_BUS_NUM                (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2)
-#define PHBS_PER_CALGARY       4
+/*
+ * The maximum PHB bus number.
+ * x3950M2 (rare): 8 chassis, 48 PHBs per chassis = 384
+ * x3950M2: 4 chassis, 48 PHBs per chassis        = 192
+ * x3950 (PCIE): 8 chassis, 32 PHBs per chassis   = 256
+ * x3950 (PCIX): 8 chassis, 16 PHBs per chassis   = 128
+ */
+#define MAX_PHB_BUS_NUM                384
+
+#define PHBS_PER_CALGARY         4
 
 /* register offsets in Calgary's internal register space */
 static const unsigned long tar_offsets[] = {
index 8e1aac86b50c6dcce26df41a1728ea21cf2a54e8..e3af342fe83ae7a57b8f6db6de4fb9541c4ab15e 100644 (file)
@@ -228,6 +228,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"),
                },
        },
+       {       /* Handle problems with rebooting on Dell T7400's */
+               .callback = set_bios_reboot,
+               .ident = "Dell Precision T7400",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"),
+               },
+       },
        {       /* Handle problems with rebooting on HP laptops */
                .callback = set_bios_reboot,
                .ident = "HP Compaq Laptop",
index a867940a6dfc4dfb31ac1f28a54ccb98d11aff46..de3b63ae3da26300297e315a6f7a9b5157d429ee 100644 (file)
 #include <asm/cpu.h>
 #include <asm/stackprotector.h>
 
-#ifdef CONFIG_DEBUG_PER_CPU_MAPS
-# define DBG(fmt, ...) pr_dbg(fmt, ##__VA_ARGS__)
-#else
-# define DBG(fmt, ...) do { if (0) pr_dbg(fmt, ##__VA_ARGS__); } while (0)
-#endif
-
 DEFINE_PER_CPU(int, cpu_number);
 EXPORT_PER_CPU_SYMBOL(cpu_number);
 
@@ -247,7 +241,7 @@ void __init setup_per_cpu_areas(void)
 #endif
 #endif
                /*
-                * Up to this point, the boot CPU has been using .data.init
+                * Up to this point, the boot CPU has been using .init.data
                 * area.  Reload any changed state for the boot CPU.
                 */
                if (cpu == boot_cpu_id)
index 7ded57896c0a1271f653ea14aaaf309e0dcb96c0..cb22acf3ed099de3a256f2f482ae1cdcd5338320 100644 (file)
@@ -93,7 +93,7 @@ static int __init sfi_parse_ioapic(struct sfi_table_header *table)
        pentry = (struct sfi_apic_table_entry *)sb->pentry;
 
        for (i = 0; i < num; i++) {
-               mp_register_ioapic(i, pentry->phys_addr, gsi_end + 1);
+               mp_register_ioapic(i, pentry->phys_addr, gsi_top);
                pentry++;
        }
 
index 37462f1ddba54d1ad3af14a682efb1e71dc6df96..c4f33b2e77d6076cef4bb7d337eceecb95b1bbff 100644 (file)
@@ -686,7 +686,7 @@ static void __cpuinit do_fork_idle(struct work_struct *work)
 static void __cpuinit announce_cpu(int cpu, int apicid)
 {
        static int current_node = -1;
-       int node = cpu_to_node(cpu);
+       int node = early_cpu_to_node(cpu);
 
        if (system_state == SYSTEM_BOOTING) {
                if (node != current_node) {
index 2cc249718c46e47ca28dd9e48ff1691a3c39d185..d0bb52296fa3a8f564cdb1964107e677494859ed 100644 (file)
@@ -97,7 +97,7 @@ SECTIONS
                HEAD_TEXT
 #ifdef CONFIG_X86_32
                . = ALIGN(PAGE_SIZE);
-               *(.text.page_aligned)
+               *(.text..page_aligned)
 #endif
                . = ALIGN(8);
                _stext = .;
@@ -305,7 +305,7 @@ SECTIONS
        . = ALIGN(PAGE_SIZE);
        .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
                __bss_start = .;
-               *(.bss.page_aligned)
+               *(.bss..page_aligned)
                *(.bss)
                . = ALIGN(4);
                __bss_stop = .;
index 81563e76e28f28a6f046630e1c13dbffd7215232..a6f695d76928675008a99f2030b00299856840c4 100644 (file)
@@ -1815,6 +1815,9 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 
                spte |= PT_WRITABLE_MASK;
 
+               if (!tdp_enabled && !(pte_access & ACC_WRITE_MASK))
+                       spte &= ~PT_USER_MASK;
+
                /*
                 * Optimization: for pte sync, if spte was writable the hash
                 * lookup is unnecessary (and expensive). Write protection
@@ -1870,6 +1873,8 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 
                        child = page_header(pte & PT64_BASE_ADDR_MASK);
                        mmu_page_remove_parent_pte(child, sptep);
+                       __set_spte(sptep, shadow_trap_nonpresent_pte);
+                       kvm_flush_remote_tlbs(vcpu->kvm);
                } else if (pfn != spte_to_pfn(*sptep)) {
                        pgprintk("hfn old %lx new %lx\n",
                                 spte_to_pfn(*sptep), pfn);
index 96dc232bfc56562a9cf0b178df962ba33a5c3c43..ce438e0fdd268f394995d604070b8b2aad783e4d 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/ftrace_event.h>
 #include <linux/slab.h>
 
+#include <asm/tlbflush.h>
 #include <asm/desc.h>
 
 #include <asm/virtext.h>
@@ -56,6 +57,8 @@ MODULE_LICENSE("GPL");
 
 #define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
 
+static bool erratum_383_found __read_mostly;
+
 static const u32 host_save_user_msrs[] = {
 #ifdef CONFIG_X86_64
        MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE,
@@ -374,6 +377,31 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
        svm->vmcb->control.event_inj_err = error_code;
 }
 
+static void svm_init_erratum_383(void)
+{
+       u32 low, high;
+       int err;
+       u64 val;
+
+       /* Only Fam10h is affected */
+       if (boot_cpu_data.x86 != 0x10)
+               return;
+
+       /* Use _safe variants to not break nested virtualization */
+       val = native_read_msr_safe(MSR_AMD64_DC_CFG, &err);
+       if (err)
+               return;
+
+       val |= (1ULL << 47);
+
+       low  = lower_32_bits(val);
+       high = upper_32_bits(val);
+
+       native_write_msr_safe(MSR_AMD64_DC_CFG, low, high);
+
+       erratum_383_found = true;
+}
+
 static int has_svm(void)
 {
        const char *msg;
@@ -429,6 +457,8 @@ static int svm_hardware_enable(void *garbage)
 
        wrmsrl(MSR_VM_HSAVE_PA, page_to_pfn(sd->save_area) << PAGE_SHIFT);
 
+       svm_init_erratum_383();
+
        return 0;
 }
 
@@ -1410,8 +1440,59 @@ static int nm_interception(struct vcpu_svm *svm)
        return 1;
 }
 
-static int mc_interception(struct vcpu_svm *svm)
+static bool is_erratum_383(void)
 {
+       int err, i;
+       u64 value;
+
+       if (!erratum_383_found)
+               return false;
+
+       value = native_read_msr_safe(MSR_IA32_MC0_STATUS, &err);
+       if (err)
+               return false;
+
+       /* Bit 62 may or may not be set for this mce */
+       value &= ~(1ULL << 62);
+
+       if (value != 0xb600000000010015ULL)
+               return false;
+
+       /* Clear MCi_STATUS registers */
+       for (i = 0; i < 6; ++i)
+               native_write_msr_safe(MSR_IA32_MCx_STATUS(i), 0, 0);
+
+       value = native_read_msr_safe(MSR_IA32_MCG_STATUS, &err);
+       if (!err) {
+               u32 low, high;
+
+               value &= ~(1ULL << 2);
+               low    = lower_32_bits(value);
+               high   = upper_32_bits(value);
+
+               native_write_msr_safe(MSR_IA32_MCG_STATUS, low, high);
+       }
+
+       /* Flush tlb to evict multi-match entries */
+       __flush_tlb_all();
+
+       return true;
+}
+
+static void svm_handle_mce(struct vcpu_svm *svm)
+{
+       if (is_erratum_383()) {
+               /*
+                * Erratum 383 triggered. Guest state is corrupt so kill the
+                * guest.
+                */
+               pr_err("KVM: Guest triggered AMD Erratum 383\n");
+
+               set_bit(KVM_REQ_TRIPLE_FAULT, &svm->vcpu.requests);
+
+               return;
+       }
+
        /*
         * On an #MC intercept the MCE handler is not called automatically in
         * the host. So do it by hand here.
@@ -1420,6 +1501,11 @@ static int mc_interception(struct vcpu_svm *svm)
                "int $0x12\n");
        /* not sure if we ever come back to this point */
 
+       return;
+}
+
+static int mc_interception(struct vcpu_svm *svm)
+{
        return 1;
 }
 
@@ -3088,6 +3174,14 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
                vcpu->arch.regs_avail &= ~(1 << VCPU_EXREG_PDPTR);
                vcpu->arch.regs_dirty &= ~(1 << VCPU_EXREG_PDPTR);
        }
+
+       /*
+        * We need to handle MC intercepts here before the vcpu has a chance to
+        * change the physical cpu
+        */
+       if (unlikely(svm->vmcb->control.exit_code ==
+                    SVM_EXIT_EXCP_BASE + MC_VECTOR))
+               svm_handle_mce(svm);
 }
 
 #undef R
index 550df481accd58d8ce23e7c96549f0507b1365b8..787c52ca49c3cf54dcb7cdc5712275d586460252 100644 (file)
@@ -3,12 +3,6 @@
 #include <linux/module.h>
 #include <linux/bootmem.h>
 
-#ifdef CONFIG_DEBUG_PER_CPU_MAPS
-# define DBG(x...) printk(KERN_DEBUG x)
-#else
-# define DBG(x...)
-#endif
-
 /*
  * Which logical CPUs are on which nodes
  */
index acc15b23b74342df6188d0fd0e7b356e1530e8bb..64121a18b8cb33902b6161435136aa86b619a152 100644 (file)
@@ -302,7 +302,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                return -EINVAL;
        }
 
-       new  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
+       new  = kzalloc(sizeof(struct memtype), GFP_KERNEL);
        if (!new)
                return -ENOMEM;
 
index f537087bb740933d5d412c619bb3d5107b53c3b0..f20eeec85a862c7dd044e15993aac3cd8c13214c 100644 (file)
@@ -226,6 +226,7 @@ int rbt_memtype_check_insert(struct memtype *new, unsigned long *ret_type)
                if (ret_type)
                        new->type = *ret_type;
 
+               new->subtree_max_end = new->end;
                memtype_rb_insert(&memtype_rbroot, new);
        }
        return err;
index 97da2ba9344b4ca7fa1f08d7cd015fe77a332ea6..6fdb3ec30c3197e15fc54e18c91291f5eb403450 100644 (file)
@@ -96,6 +96,7 @@ EXPORT_SYMBOL(pcibios_align_resource);
  *       the fact the PCI specs explicitly allow address decoders to be
  *       shared between expansion ROMs and other resource regions, it's
  *       at least dangerous)
+ *     - bad resource sizes or overlaps with other regions
  *
  *  Our solution:
  *     (1) Allocate resources for all buses behind PCI-to-PCI bridges.
@@ -136,6 +137,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
                                         * child resource allocations in this
                                         * range.
                                         */
+                                       r->start = r->end = 0;
                                        r->flags = 0;
                                }
                        }
index 0db5eaf54560b3ec1d8083ee8e69d8a1057a045c..8d460eaf524f1d6f1a54b3853de221e7b38d9e6d 100644 (file)
  */
 static void __devinit pcibios_fixup_peer_bridges(void)
 {
-       int n, devfn;
-       long node;
+       int n;
 
        if (pcibios_last_bus <= 0 || pcibios_last_bus > 0xff)
                return;
        DBG("PCI: Peer bridge fixup\n");
 
-       for (n=0; n <= pcibios_last_bus; n++) {
-               u32 l;
-               if (pci_find_bus(0, n))
-                       continue;
-               node = get_mp_bus_to_node(n);
-               for (devfn = 0; devfn < 256; devfn += 8) {
-                       if (!raw_pci_read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
-                           l != 0x0000 && l != 0xffff) {
-                               DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l);
-                               printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
-                               pci_scan_bus_on_node(n, &pci_root_ops, node);
-                               break;
-                       }
-               }
-       }
+       for (n=0; n <= pcibios_last_bus; n++)
+               pcibios_scan_specific_bus(n);
 }
 
 int __init pci_legacy_init(void)
@@ -50,6 +36,28 @@ int __init pci_legacy_init(void)
        return 0;
 }
 
+void pcibios_scan_specific_bus(int busn)
+{
+       int devfn;
+       long node;
+       u32 l;
+
+       if (pci_find_bus(0, busn))
+               return;
+
+       node = get_mp_bus_to_node(busn);
+       for (devfn = 0; devfn < 256; devfn += 8) {
+               if (!raw_pci_read(0, busn, devfn, PCI_VENDOR_ID, 2, &l) &&
+                   l != 0x0000 && l != 0xffff) {
+                       DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l);
+                       printk(KERN_INFO "PCI: Discovered peer bus %02x\n", busn);
+                       pci_scan_bus_on_node(busn, &pci_root_ops, node);
+                       return;
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(pcibios_scan_specific_bus);
+
 int __init pci_subsys_init(void)
 {
        /*
index 0a979f3e5b8a7596aaf7d402cf73b0bb7eace8a9..1290ba54b3506ba5325cecc01ac52853b36d0f26 100644 (file)
@@ -105,6 +105,8 @@ static void __save_processor_state(struct saved_context *ctxt)
        ctxt->cr4 = read_cr4();
        ctxt->cr8 = read_cr8();
 #endif
+       ctxt->misc_enable_saved = !rdmsrl_safe(MSR_IA32_MISC_ENABLE,
+                                              &ctxt->misc_enable);
 }
 
 /* Needed by apm.c */
@@ -152,6 +154,8 @@ static void fix_processor_context(void)
  */
 static void __restore_processor_state(struct saved_context *ctxt)
 {
+       if (ctxt->misc_enable_saved)
+               wrmsrl(MSR_IA32_MISC_ENABLE, ctxt->misc_enable);
        /*
         * control registers
         */
index 987267f79bf5154648cb729cedf29e712fa58ab3..a9c6611080347bd4368beff2ab582d07347fa256 100644 (file)
@@ -60,6 +60,6 @@ static void xen_vcpu_notify_restore(void *data)
 
 void xen_arch_resume(void)
 {
-       smp_call_function(xen_vcpu_notify_restore,
-                              (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
+       on_each_cpu(xen_vcpu_notify_restore,
+                   (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
 }
index bc0733359a8852a12288f083c2420f4c9734948e..e367e30264366d82c17dc66d157a2aa2534388bc 100644 (file)
@@ -105,7 +105,6 @@ good_area:
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-survive:
        fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0);
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
@@ -146,15 +145,10 @@ bad_area:
         */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (is_global_init(current)) {
-               yield();
-               down_read(&mm->mmap_sem);
-               goto survive;
-       }
-       printk("VM: killing process %s\n", current->comm);
-       if (user_mode(regs))
-               do_group_exit(SIGKILL);
-       bad_page_fault(regs, address, SIGKILL);
+       if (!user_mode(regs))
+               bad_page_fault(regs, address, SIGKILL);
+       else
+               pagefault_out_of_memory();
        return;
 
 do_sigbus:
index 3bc5579d6f543fa57783e09268707178de26c4b7..f0640d7f800f7164c5b04a59791410a029a48cc4 100644 (file)
@@ -467,6 +467,9 @@ static int blk_init_free_list(struct request_queue *q)
 {
        struct request_list *rl = &q->rq;
 
+       if (unlikely(rl->rq_pool))
+               return 0;
+
        rl->count[BLK_RW_SYNC] = rl->count[BLK_RW_ASYNC] = 0;
        rl->starved[BLK_RW_SYNC] = rl->starved[BLK_RW_ASYNC] = 0;
        rl->elvpriv = 0;
@@ -570,9 +573,17 @@ EXPORT_SYMBOL(blk_init_queue);
 struct request_queue *
 blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
 {
-       struct request_queue *q = blk_alloc_queue_node(GFP_KERNEL, node_id);
+       struct request_queue *uninit_q, *q;
+
+       uninit_q = blk_alloc_queue_node(GFP_KERNEL, node_id);
+       if (!uninit_q)
+               return NULL;
+
+       q = blk_init_allocated_queue_node(uninit_q, rfn, lock, node_id);
+       if (!q)
+               blk_cleanup_queue(uninit_q);
 
-       return blk_init_allocated_queue_node(q, rfn, lock, node_id);
+       return q;
 }
 EXPORT_SYMBOL(blk_init_queue_node);
 
@@ -592,10 +603,8 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn,
                return NULL;
 
        q->node = node_id;
-       if (blk_init_free_list(q)) {
-               kmem_cache_free(blk_requestq_cachep, q);
+       if (blk_init_free_list(q))
                return NULL;
-       }
 
        q->request_fn           = rfn;
        q->prep_rq_fn           = NULL;
@@ -618,7 +627,6 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn,
                return q;
        }
 
-       blk_put_queue(q);
        return NULL;
 }
 EXPORT_SYMBOL(blk_init_allocated_queue_node);
@@ -1141,13 +1149,10 @@ void init_request_from_bio(struct request *req, struct bio *bio)
        else
                req->cmd_flags |= bio->bi_rw & REQ_FAILFAST_MASK;
 
-       if (unlikely(bio_rw_flagged(bio, BIO_RW_DISCARD))) {
+       if (bio_rw_flagged(bio, BIO_RW_DISCARD))
                req->cmd_flags |= REQ_DISCARD;
-               if (bio_rw_flagged(bio, BIO_RW_BARRIER))
-                       req->cmd_flags |= REQ_SOFTBARRIER;
-       } else if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER)))
+       if (bio_rw_flagged(bio, BIO_RW_BARRIER))
                req->cmd_flags |= REQ_HARDBARRIER;
-
        if (bio_rw_flagged(bio, BIO_RW_SYNCIO))
                req->cmd_flags |= REQ_RW_SYNC;
        if (bio_rw_flagged(bio, BIO_RW_META))
@@ -1578,7 +1583,7 @@ void submit_bio(int rw, struct bio *bio)
         * If it's a regular read/write or a barrier with data attached,
         * go through the normal accounting stuff before submission.
         */
-       if (bio_has_data(bio)) {
+       if (bio_has_data(bio) && !(rw & (1 << BIO_RW_DISCARD))) {
                if (rw & WRITE) {
                        count_vm_events(PGPGOUT, count);
                } else {
index ed897b5ef315dedfe01d0fe8817ef2259b770252..7982b830db58df900fb679919c81edfc0ee34689 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/rbtree.h>
 #include <linux/ioprio.h>
 #include <linux/blktrace_api.h>
-#include "blk-cgroup.h"
+#include "cfq.h"
 
 /*
  * tunables
@@ -64,6 +64,9 @@ static DEFINE_PER_CPU(unsigned long, cfq_ioc_count);
 static struct completion *ioc_gone;
 static DEFINE_SPINLOCK(ioc_gone_lock);
 
+static DEFINE_SPINLOCK(cic_index_lock);
+static DEFINE_IDA(cic_index_ida);
+
 #define CFQ_PRIO_LISTS         IOPRIO_BE_NR
 #define cfq_class_idle(cfqq)   ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
 #define cfq_class_rt(cfqq)     ((cfqq)->ioprio_class == IOPRIO_CLASS_RT)
@@ -271,6 +274,7 @@ struct cfq_data {
        unsigned int cfq_latency;
        unsigned int cfq_group_isolation;
 
+       unsigned int cic_index;
        struct list_head cic_list;
 
        /*
@@ -430,6 +434,24 @@ static inline void cic_set_cfqq(struct cfq_io_context *cic,
        cic->cfqq[is_sync] = cfqq;
 }
 
+#define CIC_DEAD_KEY   1ul
+#define CIC_DEAD_INDEX_SHIFT   1
+
+static inline void *cfqd_dead_key(struct cfq_data *cfqd)
+{
+       return (void *)(cfqd->cic_index << CIC_DEAD_INDEX_SHIFT | CIC_DEAD_KEY);
+}
+
+static inline struct cfq_data *cic_to_cfqd(struct cfq_io_context *cic)
+{
+       struct cfq_data *cfqd = cic->key;
+
+       if (unlikely((unsigned long) cfqd & CIC_DEAD_KEY))
+               return NULL;
+
+       return cfqd;
+}
+
 /*
  * We regard a request as SYNC, if it's either a read or has the SYNC bit
  * set (in which case it could also be direct WRITE).
@@ -857,7 +879,7 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg)
        if (!RB_EMPTY_NODE(&cfqg->rb_node))
                cfq_rb_erase(&cfqg->rb_node, st);
        cfqg->saved_workload_slice = 0;
-       blkiocg_update_dequeue_stats(&cfqg->blkg, 1);
+       cfq_blkiocg_update_dequeue_stats(&cfqg->blkg, 1);
 }
 
 static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq)
@@ -917,8 +939,8 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg,
 
        cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime,
                                        st->min_vdisktime);
-       blkiocg_update_timeslice_used(&cfqg->blkg, used_sl);
-       blkiocg_set_start_empty_time(&cfqg->blkg);
+       cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl);
+       cfq_blkiocg_set_start_empty_time(&cfqg->blkg);
 }
 
 #ifdef CONFIG_CFQ_GROUP_IOSCHED
@@ -973,7 +995,7 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)
 
        /* Add group onto cgroup list */
        sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
-       blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd,
+       cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd,
                                        MKDEV(major, minor));
        cfqg->weight = blkcg_get_weight(blkcg, cfqg->blkg.dev);
 
@@ -1057,7 +1079,7 @@ static void cfq_release_cfq_groups(struct cfq_data *cfqd)
                 * it from cgroup list, then it will take care of destroying
                 * cfqg also.
                 */
-               if (!blkiocg_del_blkio_group(&cfqg->blkg))
+               if (!cfq_blkiocg_del_blkio_group(&cfqg->blkg))
                        cfq_destroy_cfqg(cfqd, cfqg);
        }
 }
@@ -1399,10 +1421,10 @@ static void cfq_reposition_rq_rb(struct cfq_queue *cfqq, struct request *rq)
 {
        elv_rb_del(&cfqq->sort_list, rq);
        cfqq->queued[rq_is_sync(rq)]--;
-       blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(rq),
-                                               rq_is_sync(rq));
+       cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg,
+                                       rq_data_dir(rq), rq_is_sync(rq));
        cfq_add_rq_rb(rq);
-       blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
+       cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
                        &cfqq->cfqd->serving_group->blkg, rq_data_dir(rq),
                        rq_is_sync(rq));
 }
@@ -1460,8 +1482,8 @@ static void cfq_remove_request(struct request *rq)
        cfq_del_rq_rb(rq);
 
        cfqq->cfqd->rq_queued--;
-       blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(rq),
-                                               rq_is_sync(rq));
+       cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg,
+                                       rq_data_dir(rq), rq_is_sync(rq));
        if (rq_is_meta(rq)) {
                WARN_ON(!cfqq->meta_pending);
                cfqq->meta_pending--;
@@ -1496,8 +1518,8 @@ static void cfq_merged_request(struct request_queue *q, struct request *req,
 static void cfq_bio_merged(struct request_queue *q, struct request *req,
                                struct bio *bio)
 {
-       blkiocg_update_io_merged_stats(&(RQ_CFQG(req))->blkg, bio_data_dir(bio),
-                                       cfq_bio_sync(bio));
+       cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(req))->blkg,
+                                       bio_data_dir(bio), cfq_bio_sync(bio));
 }
 
 static void
@@ -1517,8 +1539,8 @@ cfq_merged_requests(struct request_queue *q, struct request *rq,
        if (cfqq->next_rq == next)
                cfqq->next_rq = rq;
        cfq_remove_request(next);
-       blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(next),
-                                       rq_is_sync(next));
+       cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg,
+                                       rq_data_dir(next), rq_is_sync(next));
 }
 
 static int cfq_allow_merge(struct request_queue *q, struct request *rq,
@@ -1549,7 +1571,7 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq,
 static inline void cfq_del_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
        del_timer(&cfqd->idle_slice_timer);
-       blkiocg_update_idle_time_stats(&cfqq->cfqg->blkg);
+       cfq_blkiocg_update_idle_time_stats(&cfqq->cfqg->blkg);
 }
 
 static void __cfq_set_active_queue(struct cfq_data *cfqd,
@@ -1558,7 +1580,7 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd,
        if (cfqq) {
                cfq_log_cfqq(cfqd, cfqq, "set_active wl_prio:%d wl_type:%d",
                                cfqd->serving_prio, cfqd->serving_type);
-               blkiocg_update_avg_queue_size_stats(&cfqq->cfqg->blkg);
+               cfq_blkiocg_update_avg_queue_size_stats(&cfqq->cfqg->blkg);
                cfqq->slice_start = 0;
                cfqq->dispatch_start = jiffies;
                cfqq->allocated_slice = 0;
@@ -1889,7 +1911,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
        sl = cfqd->cfq_slice_idle;
 
        mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
-       blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg);
+       cfq_blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg);
        cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu", sl);
 }
 
@@ -1909,7 +1931,7 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq)
        elv_dispatch_sort(q, rq);
 
        cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++;
-       blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq),
+       cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq),
                                        rq_data_dir(rq), rq_is_sync(rq));
 }
 
@@ -1964,6 +1986,15 @@ static void cfq_setup_merge(struct cfq_queue *cfqq, struct cfq_queue *new_cfqq)
        int process_refs, new_process_refs;
        struct cfq_queue *__cfqq;
 
+       /*
+        * If there are no process references on the new_cfqq, then it is
+        * unsafe to follow the ->new_cfqq chain as other cfqq's in the
+        * chain may have dropped their last reference (not just their
+        * last process reference).
+        */
+       if (!cfqq_process_refs(new_cfqq))
+               return;
+
        /* Avoid a circular list and skip interim queue merges */
        while ((__cfqq = new_cfqq->new_cfqq)) {
                if (__cfqq == cfqq)
@@ -1972,17 +2003,17 @@ static void cfq_setup_merge(struct cfq_queue *cfqq, struct cfq_queue *new_cfqq)
        }
 
        process_refs = cfqq_process_refs(cfqq);
+       new_process_refs = cfqq_process_refs(new_cfqq);
        /*
         * If the process for the cfqq has gone away, there is no
         * sense in merging the queues.
         */
-       if (process_refs == 0)
+       if (process_refs == 0 || new_process_refs == 0)
                return;
 
        /*
         * Merge in the direction of the lesser amount of work.
         */
-       new_process_refs = cfqq_process_refs(new_cfqq);
        if (new_process_refs >= process_refs) {
                cfqq->new_cfqq = new_cfqq;
                atomic_add(process_refs, &new_cfqq->ref);
@@ -2510,11 +2541,12 @@ static void cfq_cic_free(struct cfq_io_context *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(!cic->dead_key);
+       BUG_ON(!(dead_key & CIC_DEAD_KEY));
 
        spin_lock_irqsave(&ioc->lock, flags);
-       radix_tree_delete(&ioc->radix_root, cic->dead_key);
+       radix_tree_delete(&ioc->radix_root, dead_key >> CIC_DEAD_INDEX_SHIFT);
        hlist_del_rcu(&cic->cic_list);
        spin_unlock_irqrestore(&ioc->lock, flags);
 
@@ -2537,15 +2569,10 @@ static void cfq_free_io_context(struct io_context *ioc)
        __call_for_each_cic(ioc, cic_free_func);
 }
 
-static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+static void cfq_put_cooperator(struct cfq_queue *cfqq)
 {
        struct cfq_queue *__cfqq, *next;
 
-       if (unlikely(cfqq == cfqd->active_queue)) {
-               __cfq_slice_expired(cfqd, cfqq, 0);
-               cfq_schedule_dispatch(cfqd);
-       }
-
        /*
         * If this queue was scheduled to merge with another queue, be
         * sure to drop the reference taken on that queue (and others in
@@ -2561,6 +2588,16 @@ static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
                cfq_put_queue(__cfqq);
                __cfqq = next;
        }
+}
+
+static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+       if (unlikely(cfqq == cfqd->active_queue)) {
+               __cfq_slice_expired(cfqd, cfqq, 0);
+               cfq_schedule_dispatch(cfqd);
+       }
+
+       cfq_put_cooperator(cfqq);
 
        cfq_put_queue(cfqq);
 }
@@ -2573,11 +2610,10 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd,
        list_del_init(&cic->queue_list);
 
        /*
-        * Make sure key == NULL is seen for dead queues
+        * Make sure dead mark is seen for dead queues
         */
        smp_wmb();
-       cic->dead_key = (unsigned long) cic->key;
-       cic->key = NULL;
+       cic->key = cfqd_dead_key(cfqd);
 
        if (ioc->ioc_data == cic)
                rcu_assign_pointer(ioc->ioc_data, NULL);
@@ -2596,7 +2632,7 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd,
 static void cfq_exit_single_io_context(struct io_context *ioc,
                                       struct cfq_io_context *cic)
 {
-       struct cfq_data *cfqd = cic->key;
+       struct cfq_data *cfqd = cic_to_cfqd(cic);
 
        if (cfqd) {
                struct request_queue *q = cfqd->queue;
@@ -2609,7 +2645,7 @@ static void cfq_exit_single_io_context(struct io_context *ioc,
                 * race between exiting task and queue
                 */
                smp_read_barrier_depends();
-               if (cic->key)
+               if (cic->key == cfqd)
                        __cfq_exit_single_io_context(cfqd, cic);
 
                spin_unlock_irqrestore(q->queue_lock, flags);
@@ -2689,7 +2725,7 @@ static void cfq_init_prio_data(struct cfq_queue *cfqq, struct io_context *ioc)
 
 static void changed_ioprio(struct io_context *ioc, struct cfq_io_context *cic)
 {
-       struct cfq_data *cfqd = cic->key;
+       struct cfq_data *cfqd = cic_to_cfqd(cic);
        struct cfq_queue *cfqq;
        unsigned long flags;
 
@@ -2746,7 +2782,7 @@ static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 static void changed_cgroup(struct io_context *ioc, struct cfq_io_context *cic)
 {
        struct cfq_queue *sync_cfqq = cic_to_cfqq(cic, 1);
-       struct cfq_data *cfqd = cic->key;
+       struct cfq_data *cfqd = cic_to_cfqd(cic);
        unsigned long flags;
        struct request_queue *q;
 
@@ -2883,12 +2919,13 @@ cfq_drop_dead_cic(struct cfq_data *cfqd, struct io_context *ioc,
        unsigned long flags;
 
        WARN_ON(!list_empty(&cic->queue_list));
+       BUG_ON(cic->key != cfqd_dead_key(cfqd));
 
        spin_lock_irqsave(&ioc->lock, flags);
 
        BUG_ON(ioc->ioc_data == cic);
 
-       radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd);
+       radix_tree_delete(&ioc->radix_root, cfqd->cic_index);
        hlist_del_rcu(&cic->cic_list);
        spin_unlock_irqrestore(&ioc->lock, flags);
 
@@ -2900,7 +2937,6 @@ cfq_cic_lookup(struct cfq_data *cfqd, struct io_context *ioc)
 {
        struct cfq_io_context *cic;
        unsigned long flags;
-       void *k;
 
        if (unlikely(!ioc))
                return NULL;
@@ -2917,13 +2953,11 @@ cfq_cic_lookup(struct cfq_data *cfqd, struct io_context *ioc)
        }
 
        do {
-               cic = radix_tree_lookup(&ioc->radix_root, (unsigned long) cfqd);
+               cic = radix_tree_lookup(&ioc->radix_root, cfqd->cic_index);
                rcu_read_unlock();
                if (!cic)
                        break;
-               /* ->key must be copied to avoid race with cfq_exit_queue() */
-               k = cic->key;
-               if (unlikely(!k)) {
+               if (unlikely(cic->key != cfqd)) {
                        cfq_drop_dead_cic(cfqd, ioc, cic);
                        rcu_read_lock();
                        continue;
@@ -2956,7 +2990,7 @@ static int cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
 
                spin_lock_irqsave(&ioc->lock, flags);
                ret = radix_tree_insert(&ioc->radix_root,
-                                               (unsigned long) cfqd, cic);
+                                               cfqd->cic_index, cic);
                if (!ret)
                        hlist_add_head_rcu(&cic->cic_list, &ioc->cic_list);
                spin_unlock_irqrestore(&ioc->lock, flags);
@@ -3223,7 +3257,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                                cfq_clear_cfqq_wait_request(cfqq);
                                __blk_run_queue(cfqd->queue);
                        } else {
-                               blkiocg_update_idle_time_stats(
+                               cfq_blkiocg_update_idle_time_stats(
                                                &cfqq->cfqg->blkg);
                                cfq_mark_cfqq_must_dispatch(cfqq);
                        }
@@ -3251,7 +3285,7 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq)
        rq_set_fifo_time(rq, jiffies + cfqd->cfq_fifo_expire[rq_is_sync(rq)]);
        list_add_tail(&rq->queuelist, &cfqq->fifo);
        cfq_add_rq_rb(rq);
-       blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
+       cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
                        &cfqd->serving_group->blkg, rq_data_dir(rq),
                        rq_is_sync(rq));
        cfq_rq_enqueued(cfqd, cfqq, rq);
@@ -3339,9 +3373,9 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
        WARN_ON(!cfqq->dispatched);
        cfqd->rq_in_driver--;
        cfqq->dispatched--;
-       blkiocg_update_completion_stats(&cfqq->cfqg->blkg, rq_start_time_ns(rq),
-                       rq_io_start_time_ns(rq), rq_data_dir(rq),
-                       rq_is_sync(rq));
+       cfq_blkiocg_update_completion_stats(&cfqq->cfqg->blkg,
+                       rq_start_time_ns(rq), rq_io_start_time_ns(rq),
+                       rq_data_dir(rq), rq_is_sync(rq));
 
        cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
 
@@ -3516,6 +3550,9 @@ split_cfqq(struct cfq_io_context *cic, struct cfq_queue *cfqq)
        }
 
        cic_set_cfqq(cic, NULL, 1);
+
+       cfq_put_cooperator(cfqq);
+
        cfq_put_queue(cfqq);
        return NULL;
 }
@@ -3702,16 +3739,38 @@ static void cfq_exit_queue(struct elevator_queue *e)
 
        cfq_put_async_queues(cfqd);
        cfq_release_cfq_groups(cfqd);
-       blkiocg_del_blkio_group(&cfqd->root_group.blkg);
+       cfq_blkiocg_del_blkio_group(&cfqd->root_group.blkg);
 
        spin_unlock_irq(q->queue_lock);
 
        cfq_shutdown_timer_wq(cfqd);
 
+       spin_lock(&cic_index_lock);
+       ida_remove(&cic_index_ida, cfqd->cic_index);
+       spin_unlock(&cic_index_lock);
+
        /* Wait for cfqg->blkg->key accessors to exit their grace periods. */
        call_rcu(&cfqd->rcu, cfq_cfqd_free);
 }
 
+static int cfq_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 *cfq_init_queue(struct request_queue *q)
 {
        struct cfq_data *cfqd;
@@ -3719,10 +3778,16 @@ static void *cfq_init_queue(struct request_queue *q)
        struct cfq_group *cfqg;
        struct cfq_rb_root *st;
 
+       i = cfq_alloc_cic_index();
+       if (i < 0)
+               return NULL;
+
        cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
        if (!cfqd)
                return NULL;
 
+       cfqd->cic_index = i;
+
        /* Init root service tree */
        cfqd->grp_service_tree = CFQ_RB_ROOT;
 
@@ -3742,8 +3807,8 @@ static void *cfq_init_queue(struct request_queue *q)
         */
        atomic_set(&cfqg->ref, 1);
        rcu_read_lock();
-       blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, (void *)cfqd,
-                                       0);
+       cfq_blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg,
+                                       (void *)cfqd, 0);
        rcu_read_unlock();
 #endif
        /*
@@ -3984,6 +4049,7 @@ static void __exit cfq_exit(void)
         */
        if (elv_ioc_count_read(cfq_ioc_count))
                wait_for_completion(&all_gone);
+       ida_destroy(&cic_index_ida);
        cfq_slab_kill();
 }
 
diff --git a/block/cfq.h b/block/cfq.h
new file mode 100644 (file)
index 0000000..93448e5
--- /dev/null
@@ -0,0 +1,115 @@
+#ifndef _CFQ_H
+#define _CFQ_H
+#include "blk-cgroup.h"
+
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
+static inline void cfq_blkiocg_update_io_add_stats(struct blkio_group *blkg,
+       struct blkio_group *curr_blkg, bool direction, bool sync)
+{
+       blkiocg_update_io_add_stats(blkg, curr_blkg, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg,
+                       unsigned long dequeue)
+{
+       blkiocg_update_dequeue_stats(blkg, dequeue);
+}
+
+static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg,
+                       unsigned long time)
+{
+       blkiocg_update_timeslice_used(blkg, time);
+}
+
+static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg)
+{
+       blkiocg_set_start_empty_time(blkg);
+}
+
+static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg,
+                               bool direction, bool sync)
+{
+       blkiocg_update_io_remove_stats(blkg, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_io_merged_stats(struct blkio_group *blkg,
+               bool direction, bool sync)
+{
+       blkiocg_update_io_merged_stats(blkg, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_idle_time_stats(struct blkio_group *blkg)
+{
+       blkiocg_update_idle_time_stats(blkg);
+}
+
+static inline void
+cfq_blkiocg_update_avg_queue_size_stats(struct blkio_group *blkg)
+{
+       blkiocg_update_avg_queue_size_stats(blkg);
+}
+
+static inline void
+cfq_blkiocg_update_set_idle_time_stats(struct blkio_group *blkg)
+{
+       blkiocg_update_set_idle_time_stats(blkg);
+}
+
+static inline void cfq_blkiocg_update_dispatch_stats(struct blkio_group *blkg,
+                               uint64_t bytes, bool direction, bool sync)
+{
+       blkiocg_update_dispatch_stats(blkg, bytes, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_completion_stats(struct blkio_group *blkg, uint64_t start_time, uint64_t io_start_time, bool direction, bool sync)
+{
+       blkiocg_update_completion_stats(blkg, start_time, io_start_time,
+                               direction, sync);
+}
+
+static inline void cfq_blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
+                       struct blkio_group *blkg, void *key, dev_t dev) {
+       blkiocg_add_blkio_group(blkcg, blkg, key, dev);
+}
+
+static inline int cfq_blkiocg_del_blkio_group(struct blkio_group *blkg)
+{
+       return blkiocg_del_blkio_group(blkg);
+}
+
+#else /* CFQ_GROUP_IOSCHED */
+static inline void cfq_blkiocg_update_io_add_stats(struct blkio_group *blkg,
+       struct blkio_group *curr_blkg, bool direction, bool sync) {}
+
+static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg,
+                       unsigned long dequeue) {}
+
+static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg,
+                       unsigned long time) {}
+static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg) {}
+static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg,
+                               bool direction, bool sync) {}
+static inline void cfq_blkiocg_update_io_merged_stats(struct blkio_group *blkg,
+               bool direction, bool sync) {}
+static inline void cfq_blkiocg_update_idle_time_stats(struct blkio_group *blkg)
+{
+}
+static inline void
+cfq_blkiocg_update_avg_queue_size_stats(struct blkio_group *blkg) {}
+
+static inline void
+cfq_blkiocg_update_set_idle_time_stats(struct blkio_group *blkg) {}
+
+static inline void cfq_blkiocg_update_dispatch_stats(struct blkio_group *blkg,
+                               uint64_t bytes, bool direction, bool sync) {}
+static inline void cfq_blkiocg_update_completion_stats(struct blkio_group *blkg, uint64_t start_time, uint64_t io_start_time, bool direction, bool sync) {}
+
+static inline void cfq_blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
+                       struct blkio_group *blkg, void *key, dev_t dev) {}
+static inline int cfq_blkiocg_del_blkio_group(struct blkio_group *blkg)
+{
+       return 0;
+}
+
+#endif /* CFQ_GROUP_IOSCHED */
+#endif
index 6df2b5056b51e1347c10cb7c5f3c50d09aa21650..923a9139106c51cbdb63dca5d1c97ce81a30d316 100644 (file)
@@ -242,9 +242,11 @@ int elevator_init(struct request_queue *q, char *name)
 {
        struct elevator_type *e = NULL;
        struct elevator_queue *eq;
-       int ret = 0;
        void *data;
 
+       if (unlikely(q->elevator))
+               return 0;
+
        INIT_LIST_HEAD(&q->queue_head);
        q->last_merge = NULL;
        q->end_sector = 0;
@@ -284,7 +286,7 @@ int elevator_init(struct request_queue *q, char *name)
        }
 
        elevator_attach(q, eq, data);
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(elevator_init);
 
@@ -1097,7 +1099,7 @@ ssize_t elv_iosched_show(struct request_queue *q, char *name)
        struct elevator_type *__e;
        int len = 0;
 
-       if (!q->elevator)
+       if (!q->elevator || !blk_queue_stackable(q))
                return sprintf(name, "none\n");
 
        elv = e->elevator_type;
index d269a8f3329cc0cbe9b5bcc8120c6a5b1c5320b7..446aced33aff81d7a2c4a949abce8979006db720 100644 (file)
@@ -46,6 +46,8 @@ static unsigned long power_saving_mwait_eax;
 
 static unsigned char tsc_detected_unstable;
 static unsigned char tsc_marked_unstable;
+static unsigned char lapic_detected_unstable;
+static unsigned char lapic_marked_unstable;
 
 static void power_saving_mwait_init(void)
 {
@@ -75,9 +77,6 @@ static void power_saving_mwait_init(void)
        power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
                (highest_subcstate - 1);
 
-       for_each_online_cpu(i)
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i);
-
 #if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86)
        switch (boot_cpu_data.x86_vendor) {
        case X86_VENDOR_AMD:
@@ -86,13 +85,15 @@ static void power_saving_mwait_init(void)
                 * AMD Fam10h TSC will tick in all
                 * C/P/S0/S1 states when this bit is set.
                 */
-               if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
-                       return;
-
-               /*FALL THROUGH*/
+               if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+                       tsc_detected_unstable = 1;
+               if (!boot_cpu_has(X86_FEATURE_ARAT))
+                       lapic_detected_unstable = 1;
+               break;
        default:
-               /* TSC could halt in idle */
+               /* TSC & LAPIC could halt in idle */
                tsc_detected_unstable = 1;
+               lapic_detected_unstable = 1;
        }
 #endif
 }
@@ -180,10 +181,20 @@ static int power_saving_thread(void *data)
                                mark_tsc_unstable("TSC halts in idle");
                                tsc_marked_unstable = 1;
                        }
+                       if (lapic_detected_unstable && !lapic_marked_unstable) {
+                               int i;
+                               /* LAPIC could halt in idle, so notify users */
+                               for_each_online_cpu(i)
+                                       clockevents_notify(
+                                               CLOCK_EVT_NOTIFY_BROADCAST_ON,
+                                               &i);
+                               lapic_marked_unstable = 1;
+                       }
                        local_irq_disable();
                        cpu = smp_processor_id();
-                       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
-                               &cpu);
+                       if (lapic_marked_unstable)
+                               clockevents_notify(
+                                       CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
                        stop_critical_timings();
 
                        __monitor((void *)&current_thread_info()->flags, 0, 0);
@@ -192,8 +203,9 @@ static int power_saving_thread(void *data)
                                __mwait(power_saving_mwait_eax, 1);
 
                        start_critical_timings();
-                       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
-                               &cpu);
+                       if (lapic_marked_unstable)
+                               clockevents_notify(
+                                       CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
                        local_irq_enable();
 
                        if (jiffies > expire_time) {
index 33181ad350d5e1be00982cec40f497f0c47aa2ae..b17d8de9f6ffd5c98b7f02f610c8bc0ce1248ace 100644 (file)
 
 #define ACPI_MAX_LOOP_ITERATIONS        0xFFFF
 
+/* Maximum sleep allowed via Sleep() operator */
+
+#define ACPI_MAX_SLEEP                  20000  /* Two seconds */
+
 /******************************************************************************
  *
  * ACPI Specification constants (Do not change unless the specification changes)
index 64d1e5c2d4ae694d3fb863803521fa965ba1e07e..c3f43daa8be3b84fa33e411f8240fd4e47c87ba5 100644 (file)
@@ -80,10 +80,6 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
 acpi_status
 acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info);
 
-acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
-
-acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
-
 struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
                                                       u32 gpe_number);
 
index 9070f1fe8f17e73adfdbc91cf0981f857e7b2f09..899d68afc3c5e0bde9be08338ec14399e52c7d32 100644 (file)
@@ -125,6 +125,14 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE);
  */
 u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE);
 
+/*
+ * Optionally truncate I/O addresses to 16 bits. Provides compatibility
+ * with other ACPI implementations. NOTE: During ACPICA initialization,
+ * this value is set to TRUE if any Windows OSI strings have been
+ * requested by the BIOS.
+ */
+u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE);
+
 /* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
 
 struct acpi_table_fadt acpi_gbl_FADT;
index 5900f135dc6d93e4bd05d0abbf9ce5e4bea82cba..32391588e163c5cb650deaf6c302a97b2efae1fd 100644 (file)
@@ -90,7 +90,11 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width);
 /*
  * hwgpe - GPE support
  */
-acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
+u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
+                            struct acpi_gpe_register_info *gpe_register_info);
+
+acpi_status
+acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action);
 
 acpi_status
 acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info);
index a221ad404167158fe679adc27dd3872156f3b9fd..7c2c336006a1f316e280e990876eb6ffcd2f0e1f 100644 (file)
@@ -69,7 +69,7 @@ acpi_status
 acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
 {
        struct acpi_gpe_register_info *gpe_register_info;
-       u8 register_bit;
+       u32 register_bit;
 
        ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks);
 
@@ -78,9 +78,8 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
                return_ACPI_STATUS(AE_NOT_EXIST);
        }
 
-       register_bit = (u8)
-           (1 <<
-            (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
+       register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+                                               gpe_register_info);
 
        /* Clear the wake/run bits up front */
 
@@ -100,106 +99,6 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
        return_ACPI_STATUS(AE_OK);
 }
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ev_enable_gpe
- *
- * PARAMETERS:  gpe_event_info          - GPE to enable
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
- *              of type or number of references.
- *
- * Note: The GPE lock should be already acquired when this function is called.
- *
- ******************************************************************************/
-
-acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
-{
-       acpi_status status;
-
-
-       ACPI_FUNCTION_TRACE(ev_enable_gpe);
-
-
-       /*
-        * We will only allow a GPE to be enabled if it has either an
-        * associated method (_Lxx/_Exx) or a handler. Otherwise, the
-        * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
-        * first time it fires.
-        */
-       if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
-               return_ACPI_STATUS(AE_NO_HANDLER);
-       }
-
-       /* Ensure the HW enable masks are current */
-
-       status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
-       if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
-       }
-
-       /* Clear the GPE (of stale events) */
-
-       status = acpi_hw_clear_gpe(gpe_event_info);
-       if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
-       }
-
-       /* Enable the requested GPE */
-
-       status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
-       return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ev_disable_gpe
- *
- * PARAMETERS:  gpe_event_info          - GPE to disable
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
- *              regardless of the type or number of references.
- *
- * Note: The GPE lock should be already acquired when this function is called.
- *
- ******************************************************************************/
-
-acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
-{
-       acpi_status status;
-
-       ACPI_FUNCTION_TRACE(ev_disable_gpe);
-
-
-       /*
-        * Note: Always disable the GPE, even if we think that that it is already
-        * disabled. It is possible that the AML or some other code has enabled
-        * the GPE behind our back.
-        */
-
-       /* Ensure the HW enable masks are current */
-
-       status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
-       if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
-       }
-
-       /*
-        * Always H/W disable this GPE, even if we don't know the GPE type.
-        * Simply clear the enable bit for this particular GPE, but do not
-        * write out the current GPE enable mask since this may inadvertently
-        * enable GPEs too early. An example is a rogue GPE that has arrived
-        * during ACPICA initialization - possibly because AML or other code
-        * has enabled the GPE.
-        */
-       status = acpi_hw_low_disable_gpe(gpe_event_info);
-       return_ACPI_STATUS(status);
-}
-
 
 /*******************************************************************************
  *
@@ -451,10 +350,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
                return_VOID;
        }
 
-       /* Update the GPE register masks for return to enabled state */
-
-       (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
-
        /*
         * Take a snapshot of the GPE info for this level - we copy the info to
         * prevent a race condition with remove_handler/remove_block.
@@ -607,7 +502,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
                 * Disable the GPE, so it doesn't keep firing before the method has a
                 * chance to run (it runs asynchronously with interrupts enabled).
                 */
-               status = acpi_ev_disable_gpe(gpe_event_info);
+               status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
                if (ACPI_FAILURE(status)) {
                        ACPI_EXCEPTION((AE_INFO, status,
                                        "Unable to disable GPE[0x%2X]",
@@ -644,7 +539,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
                 * Disable the GPE. The GPE will remain disabled a handler
                 * is installed or ACPICA is restarted.
                 */
-               status = acpi_ev_disable_gpe(gpe_event_info);
+               status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
                if (ACPI_FAILURE(status)) {
                        ACPI_EXCEPTION((AE_INFO, status,
                                        "Unable to disable GPE[0x%2X]",
index 7c28f2d9fd35015189de8e13f54579b10814ec2f..341a38ce8aa6ce34e2e5a6c8653d6067ba9921d9 100644 (file)
@@ -500,6 +500,19 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
 
                        gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
                        gpe_event_info = &gpe_block->event_info[gpe_index];
+                       gpe_number = gpe_index + gpe_block->block_base_number;
+
+                       /*
+                        * If the GPE has already been enabled for runtime
+                        * signaling, make sure it remains enabled, but do not
+                        * increment its reference counter.
+                        */
+                       if (gpe_event_info->runtime_count) {
+                               acpi_set_gpe(gpe_device, gpe_number,
+                                               ACPI_GPE_ENABLE);
+                               gpe_enabled_count++;
+                               continue;
+                       }
 
                        if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
                                wake_gpe_count++;
@@ -516,7 +529,6 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
 
                        /* Enable this GPE */
 
-                       gpe_number = gpe_index + gpe_block->block_base_number;
                        status = acpi_enable_gpe(gpe_device, gpe_number,
                                                 ACPI_GPE_TYPE_RUNTIME);
                        if (ACPI_FAILURE(status)) {
index cc825023012a6b2a3f715b96337e4fbab8742645..4a531cdf79423e7f9328318fc3cbd8f4b17a4f08 100644 (file)
@@ -719,13 +719,6 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
        handler->context = context;
        handler->method_node = gpe_event_info->dispatch.method_node;
 
-       /* Disable the GPE before installing the handler */
-
-       status = acpi_ev_disable_gpe(gpe_event_info);
-       if (ACPI_FAILURE (status)) {
-               goto unlock_and_exit;
-       }
-
        /* Install the handler */
 
        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
index d5a5efc043bf7a43ac446c815370576deaa5b096..d97b8dce16681ba90886a3b0e5546cf5b7060ce8 100644 (file)
@@ -208,6 +208,44 @@ acpi_status acpi_enable_event(u32 event, u32 flags)
 
 ACPI_EXPORT_SYMBOL(acpi_enable_event)
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_clear_and_enable_gpe
+ *
+ * PARAMETERS:  gpe_event_info  - GPE to enable
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Clear the given GPE from stale events and enable it.
+ *
+ ******************************************************************************/
+static acpi_status
+acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+{
+       acpi_status status;
+
+       /*
+        * We will only allow a GPE to be enabled if it has either an
+        * associated method (_Lxx/_Exx) or a handler. Otherwise, the
+        * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
+        * first time it fires.
+        */
+       if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
+               return_ACPI_STATUS(AE_NO_HANDLER);
+       }
+
+       /* Clear the GPE (of stale events) */
+       status = acpi_hw_clear_gpe(gpe_event_info);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       /* Enable the requested GPE */
+       status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
+
+       return_ACPI_STATUS(status);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_set_gpe
@@ -249,11 +287,11 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
 
        switch (action) {
        case ACPI_GPE_ENABLE:
-               status = acpi_ev_enable_gpe(gpe_event_info);
+               status = acpi_clear_and_enable_gpe(gpe_event_info);
                break;
 
        case ACPI_GPE_DISABLE:
-               status = acpi_ev_disable_gpe(gpe_event_info);
+               status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
                break;
 
        default:
@@ -316,7 +354,11 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
 
                gpe_event_info->runtime_count++;
                if (gpe_event_info->runtime_count == 1) {
-                       status = acpi_ev_enable_gpe(gpe_event_info);
+                       status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+                       if (ACPI_SUCCESS(status)) {
+                               status = acpi_clear_and_enable_gpe(gpe_event_info);
+                       }
+
                        if (ACPI_FAILURE(status)) {
                                gpe_event_info->runtime_count--;
                                goto unlock_and_exit;
@@ -343,7 +385,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
                 */
                gpe_event_info->wakeup_count++;
                if (gpe_event_info->wakeup_count == 1) {
-                       (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
+                       status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
                }
        }
 
@@ -403,7 +445,12 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type
 
                gpe_event_info->runtime_count--;
                if (!gpe_event_info->runtime_count) {
-                       status = acpi_ev_disable_gpe(gpe_event_info);
+                       status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+                       if (ACPI_SUCCESS(status)) {
+                               status = acpi_hw_low_set_gpe(gpe_event_info,
+                                                            ACPI_GPE_DISABLE);
+                       }
+
                        if (ACPI_FAILURE(status)) {
                                gpe_event_info->runtime_count++;
                                goto unlock_and_exit;
@@ -424,7 +471,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type
 
                gpe_event_info->wakeup_count--;
                if (!gpe_event_info->wakeup_count) {
-                       (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
+                       status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
                }
        }
 
index 6d32e09327f17e35724839fa81dee69707867f1d..675aaa91a770f2a78d3e0f9e9ae134ccf95ae446 100644 (file)
@@ -201,6 +201,14 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long)
 
        acpi_ex_relinquish_interpreter();
 
+       /*
+        * For compatibility with other ACPI implementations and to prevent
+        * accidental deep sleeps, limit the sleep time to something reasonable.
+        */
+       if (how_long > ACPI_MAX_SLEEP) {
+               how_long = ACPI_MAX_SLEEP;
+       }
+
        acpi_os_sleep(how_long);
 
        /* And now we must get the interpreter again */
index bd72319a38f00fa9357bf76a01976b792e574a01..3450309c2786ca490d47eb6952059f8ae2eb89f8 100644 (file)
@@ -57,21 +57,47 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 
 /******************************************************************************
  *
- * FUNCTION:   acpi_hw_low_disable_gpe
+ * FUNCTION:   acpi_hw_gpe_register_bit
+ *
+ * PARAMETERS: gpe_event_info      - Info block for the GPE
+ *             gpe_register_info   - Info block for the GPE register
+ *
+ * RETURN:     Status
+ *
+ * DESCRIPTION:        Compute GPE enable mask with one bit corresponding to the given
+ *             GPE set.
+ *
+ ******************************************************************************/
+
+u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
+                            struct acpi_gpe_register_info *gpe_register_info)
+{
+       return (u32)1 << (gpe_event_info->gpe_number -
+                               gpe_register_info->base_gpe_number);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:   acpi_hw_low_set_gpe
  *
  * PARAMETERS: gpe_event_info      - Info block for the GPE to be disabled
+ *             action              - Enable or disable
  *
  * RETURN:     Status
  *
- * DESCRIPTION: Disable a single GPE in the enable register.
+ * DESCRIPTION: Enable or disable a single GPE in its enable register.
  *
  ******************************************************************************/
 
-acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status
+acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)
 {
        struct acpi_gpe_register_info *gpe_register_info;
        acpi_status status;
        u32 enable_mask;
+       u32 register_bit;
+
+       ACPI_FUNCTION_ENTRY();
 
        /* Get the info block for the entire GPE register */
 
@@ -87,11 +113,27 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
                return (status);
        }
 
-       /* Clear just the bit that corresponds to this GPE */
+       /* Set ot clear just the bit that corresponds to this GPE */
 
-       ACPI_CLEAR_BIT(enable_mask, ((u32)1 <<
-                                    (gpe_event_info->gpe_number -
-                                     gpe_register_info->base_gpe_number)));
+       register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+                                               gpe_register_info);
+       switch (action) {
+       case ACPI_GPE_COND_ENABLE:
+               if (!(register_bit & gpe_register_info->enable_for_run))
+                       return (AE_BAD_PARAMETER);
+
+       case ACPI_GPE_ENABLE:
+               ACPI_SET_BIT(enable_mask, register_bit);
+               break;
+
+       case ACPI_GPE_DISABLE:
+               ACPI_CLEAR_BIT(enable_mask, register_bit);
+               break;
+
+       default:
+               ACPI_ERROR((AE_INFO, "Invalid action\n"));
+               return (AE_BAD_PARAMETER);
+       }
 
        /* Write the updated enable mask */
 
@@ -116,23 +158,11 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
 acpi_status
 acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
 {
-       struct acpi_gpe_register_info *gpe_register_info;
        acpi_status status;
 
        ACPI_FUNCTION_ENTRY();
 
-       /* Get the info block for the entire GPE register */
-
-       gpe_register_info = gpe_event_info->register_info;
-       if (!gpe_register_info) {
-               return (AE_NOT_EXIST);
-       }
-
-       /* Write the entire GPE (runtime) enable register */
-
-       status = acpi_hw_write(gpe_register_info->enable_for_run,
-                              &gpe_register_info->enable_address);
-
+       status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE);
        return (status);
 }
 
@@ -150,21 +180,28 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
 
 acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
 {
+       struct acpi_gpe_register_info *gpe_register_info;
        acpi_status status;
-       u8 register_bit;
+       u32 register_bit;
 
        ACPI_FUNCTION_ENTRY();
 
-       register_bit = (u8)(1 <<
-                           (gpe_event_info->gpe_number -
-                            gpe_event_info->register_info->base_gpe_number));
+       /* Get the info block for the entire GPE register */
+
+       gpe_register_info = gpe_event_info->register_info;
+       if (!gpe_register_info) {
+               return (AE_NOT_EXIST);
+       }
+
+       register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+                                               gpe_register_info);
 
        /*
         * Write a one to the appropriate bit in the status register to
         * clear this GPE.
         */
        status = acpi_hw_write(register_bit,
-                              &gpe_event_info->register_info->status_address);
+                              &gpe_register_info->status_address);
 
        return (status);
 }
@@ -187,7 +224,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
                       acpi_event_status * event_status)
 {
        u32 in_byte;
-       u8 register_bit;
+       u32 register_bit;
        struct acpi_gpe_register_info *gpe_register_info;
        acpi_status status;
        acpi_event_status local_event_status = 0;
@@ -204,9 +241,8 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
 
        /* Get the register bitmask for this GPE */
 
-       register_bit = (u8)(1 <<
-                           (gpe_event_info->gpe_number -
-                            gpe_event_info->register_info->base_gpe_number));
+       register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+                                               gpe_register_info);
 
        /* GPE currently enabled? (enabled for runtime?) */
 
index c10d587c16418ae00b801fc6ca5a63997d30e3ab..e1d9c777b213a3f70b90e8a20f9dd5868a425c29 100644 (file)
@@ -222,6 +222,12 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
        u32 one_byte;
        u32 i;
 
+       /* Truncate address to 16 bits if requested */
+
+       if (acpi_gbl_truncate_io_addresses) {
+               address &= ACPI_UINT16_MAX;
+       }
+
        /* Validate the entire request and perform the I/O */
 
        status = acpi_hw_validate_io_request(address, width);
@@ -279,6 +285,12 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
        acpi_status status;
        u32 i;
 
+       /* Truncate address to 16 bits if requested */
+
+       if (acpi_gbl_truncate_io_addresses) {
+               address &= ACPI_UINT16_MAX;
+       }
+
        /* Validate the entire request and perform the I/O */
 
        status = acpi_hw_validate_io_request(address, width);
index 9bd6f050f299ef55b545dac56a890d8f3219bc18..4e5272c313e0ce5be2d4ead501cb3f41bf9a3e07 100644 (file)
@@ -193,6 +193,15 @@ acpi_status acpi_ns_initialize_devices(void)
                                        acpi_ns_init_one_device, NULL, &info,
                                        NULL);
 
+       /*
+        * Any _OSI requests should be completed by now. If the BIOS has
+        * requested any Windows OSI strings, we will always truncate
+        * I/O addresses to 16 bits -- for Windows compatibility.
+        */
+       if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) {
+               acpi_gbl_truncate_io_addresses = TRUE;
+       }
+
        ACPI_FREE(info.evaluate_info);
        if (ACPI_FAILURE(status)) {
                goto error_exit;
index db3946e9c66bbdcb6f215a316521ebe785b1d381..216e1e948ff6dcc5823289300453ab3516b48072 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/kref.h>
 #include <linux/rculist.h>
index 2ebc39115507e8662db312c7c3921d2a2ee248fd..864dd46c346fd33cc9c96d830d39719053c6354e 100644 (file)
@@ -781,7 +781,7 @@ static int __init erst_init(void)
        status = acpi_get_table(ACPI_SIG_ERST, 0,
                                (struct acpi_table_header **)&erst_tab);
        if (status == AE_NOT_FOUND) {
-               pr_err(ERST_PFX "Table is not found!\n");
+               pr_info(ERST_PFX "Table is not found!\n");
                goto err;
        } else if (ACPI_FAILURE(status)) {
                const char *msg = acpi_format_exception(status);
index 814b192496166297d44903a08bbf0ddf86a2e453..8f8bd736d4ff11919656e79d2ef9442b037fafff 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/kref.h>
 #include <linux/rculist.h>
 #include <linux/interrupt.h>
+#include <linux/slab.h>
 #include <acpi/atomicio.h>
 
 #define ACPI_PFX "ACPI: "
index 2815df66f6f7354f433a370a0819a91103bd50d4..01381be05e96b3dda60b1d753b81ecf5dc610dcd 100644 (file)
@@ -218,6 +218,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                },
        },
        {
+       .callback = dmi_disable_osi_vista,
+       .ident = "VGN-NS50B_L",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
+               },
+       },
+       {
        .callback = dmi_disable_osi_win7,
        .ident = "ASUS K50IJ",
        .matches = {
index fd51c4ab4829dee0f37446f32a15a4679065675c..7d857dabdde44ad8085737591be907c49b3fbf4e 100644 (file)
@@ -425,7 +425,7 @@ static int acpi_button_add(struct acpi_device *device)
                /* Button's GPE is run-wake GPE */
                acpi_enable_gpe(device->wakeup.gpe_device,
                                device->wakeup.gpe_number,
-                               ACPI_GPE_TYPE_WAKE_RUN);
+                               ACPI_GPE_TYPE_RUNTIME);
                device->wakeup.run_wake_count++;
                device->wakeup.state.enabled = 1;
        }
@@ -449,7 +449,7 @@ static int acpi_button_remove(struct acpi_device *device, int type)
        if (device->wakeup.flags.valid) {
                acpi_disable_gpe(device->wakeup.gpe_device,
                                device->wakeup.gpe_number,
-                               ACPI_GPE_TYPE_WAKE_RUN);
+                               ACPI_GPE_TYPE_RUNTIME);
                device->wakeup.run_wake_count--;
                device->wakeup.state.enabled = 0;
        }
index e61d4f8e62a54a42dd8f39b5c9647b2a08449e07..5f2027d782e8134642d777225f4c37f6120b214f 100644 (file)
@@ -79,7 +79,7 @@ enum {
        EC_FLAGS_GPE_STORM,             /* GPE storm detected */
        EC_FLAGS_HANDLERS_INSTALLED,    /* Handlers for GPE and
                                         * OpReg are installed */
-       EC_FLAGS_FROZEN,                /* Transactions are suspended */
+       EC_FLAGS_BLOCKED,               /* Transactions are blocked */
 };
 
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
@@ -293,7 +293,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
        if (t->rdata)
                memset(t->rdata, 0, t->rlen);
        mutex_lock(&ec->lock);
-       if (test_bit(EC_FLAGS_FROZEN, &ec->flags)) {
+       if (test_bit(EC_FLAGS_BLOCKED, &ec->flags)) {
                status = -EINVAL;
                goto unlock;
        }
@@ -459,7 +459,7 @@ int ec_transaction(u8 command,
 
 EXPORT_SYMBOL(ec_transaction);
 
-void acpi_ec_suspend_transactions(void)
+void acpi_ec_block_transactions(void)
 {
        struct acpi_ec *ec = first_ec;
 
@@ -468,11 +468,11 @@ void acpi_ec_suspend_transactions(void)
 
        mutex_lock(&ec->lock);
        /* Prevent transactions from being carried out */
-       set_bit(EC_FLAGS_FROZEN, &ec->flags);
+       set_bit(EC_FLAGS_BLOCKED, &ec->flags);
        mutex_unlock(&ec->lock);
 }
 
-void acpi_ec_resume_transactions(void)
+void acpi_ec_unblock_transactions(void)
 {
        struct acpi_ec *ec = first_ec;
 
@@ -481,10 +481,20 @@ void acpi_ec_resume_transactions(void)
 
        mutex_lock(&ec->lock);
        /* Allow transactions to be carried out again */
-       clear_bit(EC_FLAGS_FROZEN, &ec->flags);
+       clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
        mutex_unlock(&ec->lock);
 }
 
+void acpi_ec_unblock_transactions_early(void)
+{
+       /*
+        * Allow transactions to happen again (this function is called from
+        * atomic context during wakeup, so we don't need to acquire the mutex).
+        */
+       if (first_ec)
+               clear_bit(EC_FLAGS_BLOCKED, &first_ec->flags);
+}
+
 static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
 {
        int result;
index acf2ab24984263d7990239a395e73862cf914c5c..8a3b840c0bb268d0580cd5550c41986bf3c09662 100644 (file)
@@ -347,7 +347,6 @@ static int __init acpi_fan_init(void)
 {
        int result = 0;
 
-
 #ifdef CONFIG_ACPI_PROCFS
        acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
        if (!acpi_fan_dir)
@@ -356,7 +355,9 @@ static int __init acpi_fan_init(void)
 
        result = acpi_bus_register_driver(&acpi_fan_driver);
        if (result < 0) {
+#ifdef CONFIG_ACPI_PROCFS
                remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
+#endif
                return -ENODEV;
        }
 
index e28411367239a117f48f2773f489aa41919bcf1f..f8f190ec066e7a266101b0783a97e8f274f5a639 100644 (file)
@@ -49,8 +49,9 @@ void acpi_early_processor_set_pdc(void);
 int acpi_ec_init(void);
 int acpi_ec_ecdt_probe(void);
 int acpi_boot_ec_enable(void);
-void acpi_ec_suspend_transactions(void);
-void acpi_ec_resume_transactions(void);
+void acpi_ec_block_transactions(void);
+void acpi_ec_unblock_transactions(void);
+void acpi_ec_unblock_transactions_early(void);
 
 /*--------------------------------------------------------------------------
                                   Suspend/Resume
index b1034a9ada4e74da88970cbdc65dd9c1959d9988..38ea0cc6dc49aba88b53a503107d144fcebe992b 100644 (file)
@@ -581,6 +581,11 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
                return 0;
        }
 
+#ifdef CONFIG_SMP
+       if (pr->id >= setup_max_cpus && pr->id != 0)
+               return 0;
+#endif
+
        BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
 
        /*
index 2e8c27d48f2b75f59f0e76436ae94db5f61466a7..b1b385692f46e09f05dd55882ed3ea9c73039b74 100644 (file)
@@ -80,7 +80,7 @@ module_param(nocst, uint, 0000);
 static unsigned int latency_factor __read_mostly = 2;
 module_param(latency_factor, uint, 0644);
 
-static s64 us_to_pm_timer_ticks(s64 t)
+static u64 us_to_pm_timer_ticks(s64 t)
 {
        return div64_u64(t * PM_TIMER_FREQUENCY, 1000000);
 }
@@ -731,10 +731,10 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
 
                seq_puts(seq, "demotion[--] ");
 
-               seq_printf(seq, "latency[%03d] usage[%08d] duration[%020llu]\n",
+               seq_printf(seq, "latency[%03d] usage[%08d] duration[%020Lu]\n",
                           pr->power.states[i].latency,
                           pr->power.states[i].usage,
-                          (unsigned long long)pr->power.states[i].time);
+                          us_to_pm_timer_ticks(pr->power.states[i].time));
        }
 
       end:
@@ -861,7 +861,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
        ktime_t  kt1, kt2;
        s64 idle_time_ns;
        s64 idle_time;
-       s64 sleep_ticks = 0;
 
        pr = __get_cpu_var(processors);
 
@@ -906,8 +905,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
        idle_time = idle_time_ns;
        do_div(idle_time, NSEC_PER_USEC);
 
-       sleep_ticks = us_to_pm_timer_ticks(idle_time);
-
        /* Tell the scheduler how much we idled: */
        sched_clock_idle_wakeup_event(idle_time_ns);
 
@@ -918,7 +915,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
        cx->usage++;
 
        lapic_timer_state_broadcast(pr, cx, 0);
-       cx->time += sleep_ticks;
+       cx->time += idle_time;
        return idle_time;
 }
 
@@ -940,7 +937,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
        ktime_t  kt1, kt2;
        s64 idle_time_ns;
        s64 idle_time;
-       s64 sleep_ticks = 0;
 
 
        pr = __get_cpu_var(processors);
@@ -1022,11 +1018,10 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
                spin_unlock(&c3_lock);
        }
        kt2 = ktime_get_real();
-       idle_time_ns = ktime_to_us(ktime_sub(kt2, kt1));
+       idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
        idle_time = idle_time_ns;
        do_div(idle_time, NSEC_PER_USEC);
 
-       sleep_ticks = us_to_pm_timer_ticks(idle_time);
        /* Tell the scheduler how much we idled: */
        sched_clock_idle_wakeup_event(idle_time_ns);
 
@@ -1037,7 +1032,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
        cx->usage++;
 
        lapic_timer_state_broadcast(pr, cx, 0);
-       cx->time += sleep_ticks;
+       cx->time += idle_time;
        return idle_time;
 }
 
index 4ab2275b4461e797bf374880c97c24db72dba386..5b7c52e4a00f09001becab5df101e7e5fa4dabc8 100644 (file)
@@ -94,11 +94,13 @@ void __init acpi_old_suspend_ordering(void)
 }
 
 /**
- *     acpi_pm_disable_gpes - Disable the GPEs.
+ * acpi_pm_freeze - Disable the GPEs and suspend EC transactions.
  */
-static int acpi_pm_disable_gpes(void)
+static int acpi_pm_freeze(void)
 {
        acpi_disable_all_gpes();
+       acpi_os_wait_events_complete(NULL);
+       acpi_ec_block_transactions();
        return 0;
 }
 
@@ -112,6 +114,8 @@ static int __acpi_pm_prepare(void)
 {
        int error = acpi_sleep_prepare(acpi_target_sleep_state);
 
+       suspend_nvs_save();
+
        if (error)
                acpi_target_sleep_state = ACPI_STATE_S0;
        return error;
@@ -126,7 +130,8 @@ static int acpi_pm_prepare(void)
        int error = __acpi_pm_prepare();
 
        if (!error)
-               acpi_disable_all_gpes();
+               acpi_pm_freeze();
+
        return error;
 }
 
@@ -140,6 +145,9 @@ static void acpi_pm_finish(void)
 {
        u32 acpi_state = acpi_target_sleep_state;
 
+       suspend_nvs_free();
+       acpi_ec_unblock_transactions();
+
        if (acpi_state == ACPI_STATE_S0)
                return;
 
@@ -189,6 +197,11 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
        u32 acpi_state = acpi_suspend_states[pm_state];
        int error = 0;
 
+       error = suspend_nvs_alloc();
+
+       if (error)
+               return error;
+
        if (sleep_states[acpi_state]) {
                acpi_target_sleep_state = acpi_state;
                acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -256,6 +269,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
         * acpi_leave_sleep_state will reenable specific GPEs later
         */
        acpi_disable_all_gpes();
+       /* Allow EC transactions to happen. */
+       acpi_ec_unblock_transactions_early();
 
        local_irq_restore(flags);
        printk(KERN_DEBUG "Back to C!\n");
@@ -264,9 +279,16 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
        if (acpi_state == ACPI_STATE_S3)
                acpi_restore_state_mem();
 
+       suspend_nvs_restore();
+
        return ACPI_SUCCESS(status) ? 0 : -EFAULT;
 }
 
+static void acpi_suspend_finish(void)
+{
+       acpi_pm_finish();
+}
+
 static int acpi_suspend_state_valid(suspend_state_t pm_state)
 {
        u32 acpi_state;
@@ -288,7 +310,7 @@ static struct platform_suspend_ops acpi_suspend_ops = {
        .begin = acpi_suspend_begin,
        .prepare_late = acpi_pm_prepare,
        .enter = acpi_suspend_enter,
-       .wake = acpi_pm_finish,
+       .wake = acpi_suspend_finish,
        .end = acpi_pm_end,
 };
 
@@ -314,9 +336,9 @@ static int acpi_suspend_begin_old(suspend_state_t pm_state)
 static struct platform_suspend_ops acpi_suspend_ops_old = {
        .valid = acpi_suspend_state_valid,
        .begin = acpi_suspend_begin_old,
-       .prepare_late = acpi_pm_disable_gpes,
+       .prepare_late = acpi_pm_freeze,
        .enter = acpi_suspend_enter,
-       .wake = acpi_pm_finish,
+       .wake = acpi_suspend_finish,
        .end = acpi_pm_end,
        .recover = acpi_pm_finish,
 };
@@ -393,7 +415,7 @@ static int acpi_hibernation_begin(void)
 {
        int error;
 
-       error = s4_no_nvs ? 0 : hibernate_nvs_alloc();
+       error = s4_no_nvs ? 0 : suspend_nvs_alloc();
        if (!error) {
                acpi_target_sleep_state = ACPI_STATE_S4;
                acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -407,7 +429,7 @@ static int acpi_hibernation_pre_snapshot(void)
        int error = acpi_pm_prepare();
 
        if (!error)
-               hibernate_nvs_save();
+               suspend_nvs_save();
 
        return error;
 }
@@ -430,12 +452,6 @@ static int acpi_hibernation_enter(void)
        return ACPI_SUCCESS(status) ? 0 : -EFAULT;
 }
 
-static void acpi_hibernation_finish(void)
-{
-       hibernate_nvs_free();
-       acpi_pm_finish();
-}
-
 static void acpi_hibernation_leave(void)
 {
        /*
@@ -452,20 +468,14 @@ static void acpi_hibernation_leave(void)
                panic("ACPI S4 hardware signature mismatch");
        }
        /* Restore the NVS memory area */
-       hibernate_nvs_restore();
+       suspend_nvs_restore();
+       /* Allow EC transactions to happen. */
+       acpi_ec_unblock_transactions_early();
 }
 
-static int acpi_pm_pre_restore(void)
+static void acpi_pm_thaw(void)
 {
-       acpi_disable_all_gpes();
-       acpi_os_wait_events_complete(NULL);
-       acpi_ec_suspend_transactions();
-       return 0;
-}
-
-static void acpi_pm_restore_cleanup(void)
-{
-       acpi_ec_resume_transactions();
+       acpi_ec_unblock_transactions();
        acpi_enable_all_runtime_gpes();
 }
 
@@ -473,12 +483,12 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
        .begin = acpi_hibernation_begin,
        .end = acpi_pm_end,
        .pre_snapshot = acpi_hibernation_pre_snapshot,
-       .finish = acpi_hibernation_finish,
+       .finish = acpi_pm_finish,
        .prepare = acpi_pm_prepare,
        .enter = acpi_hibernation_enter,
        .leave = acpi_hibernation_leave,
-       .pre_restore = acpi_pm_pre_restore,
-       .restore_cleanup = acpi_pm_restore_cleanup,
+       .pre_restore = acpi_pm_freeze,
+       .restore_cleanup = acpi_pm_thaw,
 };
 
 /**
@@ -501,7 +511,7 @@ static int acpi_hibernation_begin_old(void)
 
        if (!error) {
                if (!s4_no_nvs)
-                       error = hibernate_nvs_alloc();
+                       error = suspend_nvs_alloc();
                if (!error)
                        acpi_target_sleep_state = ACPI_STATE_S4;
        }
@@ -510,12 +520,9 @@ static int acpi_hibernation_begin_old(void)
 
 static int acpi_hibernation_pre_snapshot_old(void)
 {
-       int error = acpi_pm_disable_gpes();
-
-       if (!error)
-               hibernate_nvs_save();
-
-       return error;
+       acpi_pm_freeze();
+       suspend_nvs_save();
+       return 0;
 }
 
 /*
@@ -526,12 +533,12 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = {
        .begin = acpi_hibernation_begin_old,
        .end = acpi_pm_end,
        .pre_snapshot = acpi_hibernation_pre_snapshot_old,
-       .finish = acpi_hibernation_finish,
-       .prepare = acpi_pm_disable_gpes,
+       .prepare = acpi_pm_freeze,
+       .finish = acpi_pm_finish,
        .enter = acpi_hibernation_enter,
        .leave = acpi_hibernation_leave,
-       .pre_restore = acpi_pm_pre_restore,
-       .restore_cleanup = acpi_pm_restore_cleanup,
+       .pre_restore = acpi_pm_freeze,
+       .restore_cleanup = acpi_pm_thaw,
        .recover = acpi_pm_finish,
 };
 #endif /* CONFIG_HIBERNATION */
index c79e789ed03ae39a1c771e80586a1460546672a5..f8db50a0941c286eaba3466869ab4ed4fea23452 100644 (file)
@@ -388,10 +388,12 @@ static ssize_t counter_set(struct kobject *kobj,
        if (index < num_gpes) {
                if (!strcmp(buf, "disable\n") &&
                                (status & ACPI_EVENT_FLAG_ENABLED))
-                       result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE);
+                       result = acpi_disable_gpe(handle, index,
+                                               ACPI_GPE_TYPE_RUNTIME);
                else if (!strcmp(buf, "enable\n") &&
                                !(status & ACPI_EVENT_FLAG_ENABLED))
-                       result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE);
+                       result = acpi_enable_gpe(handle, index,
+                                               ACPI_GPE_TYPE_RUNTIME);
                else if (!strcmp(buf, "clear\n") &&
                                (status & ACPI_EVENT_FLAG_SET))
                        result = acpi_clear_gpe(handle, index);
index 4b9d339a6e28875e7eb7eaa942859bc7207d799b..388747a7ef4fc261b4e09db7866bc86bb9b17570 100644 (file)
@@ -64,16 +64,13 @@ void acpi_enable_wakeup_device(u8 sleep_state)
                struct acpi_device *dev =
                        container_of(node, struct acpi_device, wakeup_list);
 
-               if (!dev->wakeup.flags.valid)
-                       continue;
-
-               if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
+               if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled
                    || sleep_state > (u32) dev->wakeup.sleep_state)
                        continue;
 
                /* The wake-up power should have been enabled already. */
-               acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
-                               ACPI_GPE_ENABLE);
+               acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+                               ACPI_GPE_TYPE_WAKE);
        }
 }
 
@@ -96,6 +93,8 @@ void acpi_disable_wakeup_device(u8 sleep_state)
                    || (sleep_state > (u32) dev->wakeup.sleep_state))
                        continue;
 
+               acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+                               ACPI_GPE_TYPE_WAKE);
                acpi_disable_wakeup_device_power(dev);
        }
 }
@@ -109,13 +108,8 @@ int __init acpi_wakeup_device_init(void)
                struct acpi_device *dev = container_of(node,
                                                       struct acpi_device,
                                                       wakeup_list);
-               /* In case user doesn't load button driver */
-               if (!dev->wakeup.flags.always_enabled ||
-                   dev->wakeup.state.enabled)
-                       continue;
-               acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
-                               ACPI_GPE_TYPE_WAKE);
-               dev->wakeup.state.enabled = 1;
+               if (dev->wakeup.flags.always_enabled)
+                       dev->wakeup.state.enabled = 1;
        }
        mutex_unlock(&acpi_device_lock);
        return 0;
index 73f883333a0d821f8052319e489f585977d59821..aa85a98d3a4ff7da59a23d95fb7e361d4bcfa7b3 100644 (file)
@@ -168,10 +168,10 @@ config ATA_BMDMA
        default y
        help
          This option adds support for SFF ATA controllers with BMDMA
-         capability.  BMDMA stands for bus-master DMA and the
-         de-facto DMA interface for SFF controllers.
+         capability.  BMDMA stands for bus-master DMA and is the
+         de facto DMA interface for SFF controllers.
 
-         If unuser, say Y.
+         If unsure, say Y.
 
 if ATA_BMDMA
 
index 8ca16f54e1ed6648365f90e935eedc9140372c98..f2522534ae6327a94678afb080eafc5dac2d9f4c 100644 (file)
@@ -1053,6 +1053,16 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
                return -ENODEV;
 
+       /*
+        * For some reason, MCP89 on MacBook 7,1 doesn't work with
+        * ahci, use ata_generic instead.
+        */
+       if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
+           pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
+           pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
+           pdev->subsystem_device == 0xcb89)
+               return -ENODEV;
+
        /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
         * At the moment, we can only use the AHCI mode. Let the users know
         * that for SAS drives they're out of luck.
index 573158a9668da008482f4c85c23cef78f4f47ad3..7107a6929deb8816121afb4ce1048bcedc2c588b 100644 (file)
  *     A generic parallel ATA driver using libata
  */
 
+enum {
+       ATA_GEN_CLASS_MATCH             = (1 << 0),
+       ATA_GEN_FORCE_DMA               = (1 << 1),
+};
+
 /**
  *     generic_set_mode        -       mode setting
  *     @link: link to set up
 static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
 {
        struct ata_port *ap = link->ap;
+       const struct pci_device_id *id = ap->host->private_data;
        int dma_enabled = 0;
        struct ata_device *dev;
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-       /* Bits 5 and 6 indicate if DMA is active on master/slave */
-       if (ap->ioaddr.bmdma_addr)
+       if (id->driver_data & ATA_GEN_FORCE_DMA) {
+               dma_enabled = 0xff;
+       } else if (ap->ioaddr.bmdma_addr) {
+               /* Bits 5 and 6 indicate if DMA is active on master/slave */
                dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+       }
 
        if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
                dma_enabled = 0xFF;
@@ -126,7 +135,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
        const struct ata_port_info *ppi[] = { &info, NULL };
 
        /* Don't use the generic entry unless instructed to do so */
-       if (id->driver_data == 1 && all_generic_ide == 0)
+       if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0)
                return -ENODEV;
 
        /* Devices that need care */
@@ -155,7 +164,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
                        return rc;
                pcim_pin_device(dev);
        }
-       return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, (void *)id, 0);
 }
 
 static struct pci_device_id ata_generic[] = {
@@ -167,7 +176,15 @@ static struct pci_device_id ata_generic[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_HINT,   PCI_DEVICE_ID_HINT_VXPROII_IDE), },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C561), },
        { PCI_DEVICE(PCI_VENDOR_ID_OPTI,   PCI_DEVICE_ID_OPTI_82C558), },
-       { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), },
+       { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE),
+         .driver_data = ATA_GEN_FORCE_DMA },
+       /*
+        * For some reason, MCP89 on MacBook 7,1 doesn't work with
+        * ahci, use ata_generic instead.
+        */
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA,
+         PCI_VENDOR_ID_APPLE, 0xcb89,
+         .driver_data = ATA_GEN_FORCE_DMA },
 #if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE)
        { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
        { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),  },
@@ -175,7 +192,8 @@ static struct pci_device_id ata_generic[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5),  },
 #endif 
        /* Must come last. If you add entries adjust this table appropriately */
-       { PCI_ANY_ID,           PCI_ANY_ID,                        PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1},
+       { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL),
+         .driver_data = ATA_GEN_CLASS_MATCH },
        { 0, },
 };
 
index 1984a6e89e84450b55c7798b83a7232f2f16e6a8..81e772a94d59857187fda27dbfe7702469fb590f 100644 (file)
@@ -324,6 +324,7 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
        struct ahci_host_priv *hpriv = ap->host->private_data;
        void __iomem *mmio = hpriv->mmio;
        void __iomem *em_mmio = mmio + hpriv->em_loc;
+       const unsigned char *msg_buf = buf;
        u32 em_ctl, msg;
        unsigned long flags;
        int i;
@@ -343,8 +344,8 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
        }
 
        for (i = 0; i < size; i += 4) {
-               msg = buf[i] | buf[i + 1] << 8 |
-                     buf[i + 2] << 16 | buf[i + 3] << 24;
+               msg = msg_buf[i] | msg_buf[i + 1] << 8 |
+                     msg_buf[i + 2] << 16 | msg_buf[i + 3] << 24;
                writel(msg, em_mmio + i);
        }
 
@@ -541,29 +542,11 @@ static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
        return -EINVAL;
 }
 
-static int ahci_is_device_present(void __iomem *port_mmio)
-{
-       u8 status = readl(port_mmio + PORT_TFDATA) & 0xff;
-
-       /* Make sure PxTFD.STS.BSY and PxTFD.STS.DRQ are 0 */
-       if (status & (ATA_BUSY | ATA_DRQ))
-               return 0;
-
-       /* Make sure PxSSTS.DET is 3h */
-       status = readl(port_mmio + PORT_SCR_STAT) & 0xf;
-       if (status != 3)
-               return 0;
-       return 1;
-}
-
 void ahci_start_engine(struct ata_port *ap)
 {
        void __iomem *port_mmio = ahci_port_base(ap);
        u32 tmp;
 
-       if (!ahci_is_device_present(port_mmio))
-               return;
-
        /* start DMA */
        tmp = readl(port_mmio + PORT_CMD);
        tmp |= PORT_CMD_START;
@@ -1892,6 +1875,9 @@ static void ahci_error_handler(struct ata_port *ap)
        }
 
        sata_pmp_error_handler(ap);
+
+       if (!ata_dev_enabled(ap->link.device))
+               ahci_stop_engine(ap);
 }
 
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
index 06b7e49e039c1e0a2e5b630fe92a1d5d33143b8a..ddf8e48627878999c17f686fcfb05dce669a2b9c 100644 (file)
@@ -4119,9 +4119,8 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
            dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) {
                ata_dev_printk(dev, KERN_WARNING,
                               "new n_sectors matches native, probably "
-                              "late HPA unlock, continuing\n");
-               /* keep using the old n_sectors */
-               dev->n_sectors = n_sectors;
+                              "late HPA unlock, n_sectors updated\n");
+               /* use the larger n_sectors */
                return 0;
        }
 
@@ -6669,6 +6668,7 @@ EXPORT_SYMBOL_GPL(ata_dummy_port_info);
 EXPORT_SYMBOL_GPL(ata_link_next);
 EXPORT_SYMBOL_GPL(ata_dev_next);
 EXPORT_SYMBOL_GPL(ata_std_bios_param);
+EXPORT_SYMBOL_GPL(ata_scsi_unlock_native_capacity);
 EXPORT_SYMBOL_GPL(ata_host_init);
 EXPORT_SYMBOL_GPL(ata_host_alloc);
 EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo);
index cfa9dd3d72530b8beabbaf272498ba843cb6e499..a54273d2c3c6a9f432ae60d49496335452ecc1d6 100644 (file)
@@ -414,6 +414,35 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
        return 0;
 }
 
+/**
+ *     ata_scsi_unlock_native_capacity - unlock native capacity
+ *     @sdev: SCSI device to adjust device capacity for
+ *
+ *     This function is called if a partition on @sdev extends beyond
+ *     the end of the device.  It requests EH to unlock HPA.
+ *
+ *     LOCKING:
+ *     Defined by the SCSI layer.  Might sleep.
+ */
+void ata_scsi_unlock_native_capacity(struct scsi_device *sdev)
+{
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
+       struct ata_device *dev;
+       unsigned long flags;
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       dev = ata_scsi_find_dev(ap, sdev);
+       if (dev && dev->n_sectors < dev->n_native_sectors) {
+               dev->flags |= ATA_DFLAG_UNLOCK_HPA;
+               dev->link->eh_info.action |= ATA_EH_RESET;
+               ata_port_schedule_eh(ap);
+       }
+
+       spin_unlock_irqrestore(ap->lock, flags);
+       ata_port_wait_eh(ap);
+}
+
 /**
  *     ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl
  *     @ap: target port
index 76640ac76888ff88ae7a330423d6bf475149282a..75b49d01780bbf1933b59852abbca49d88fa29d5 100644 (file)
@@ -1355,8 +1355,11 @@ static struct of_device_id pata_macio_match[] =
 
 static struct macio_driver pata_macio_driver =
 {
-       .name           = "pata-macio",
-       .match_table    = pata_macio_match,
+       .driver = {
+               .name           = "pata-macio",
+               .owner          = THIS_MODULE,
+               .of_match_table = pata_macio_match,
+       },
        .probe          = pata_macio_attach,
        .remove         = pata_macio_detach,
 #ifdef CONFIG_PM
@@ -1366,9 +1369,6 @@ static struct macio_driver pata_macio_driver =
 #ifdef CONFIG_PMAC_MEDIABAY
        .mediabay_event = pata_macio_mb_event,
 #endif
-       .driver = {
-               .owner          = THIS_MODULE,
-       },
 };
 
 static const struct pci_device_id pata_macio_pci_match[] = {
index 6fd1147841162272c493339284e8a2ab0b376291..21161136cad0c12d91608a79f429b4e296a67f8f 100644 (file)
@@ -1669,7 +1669,6 @@ static void nv_mcp55_freeze(struct ata_port *ap)
        mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
        mask &= ~(NV_INT_ALL_MCP55 << shift);
        writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
-       ata_sff_freeze(ap);
 }
 
 static void nv_mcp55_thaw(struct ata_port *ap)
@@ -1683,7 +1682,6 @@ static void nv_mcp55_thaw(struct ata_port *ap)
        mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
        mask |= (NV_INT_MASK_MCP55 << shift);
        writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
-       ata_sff_thaw(ap);
 }
 
 static void nv_adma_error_handler(struct ata_port *ap)
index e9250514734b14d77591187e65c7a062cc917117..be7726d7686dd1b11368948ff2cd8645a5368dbd 100644 (file)
@@ -539,12 +539,12 @@ static void sil24_config_port(struct ata_port *ap)
                writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
 
        /* zero error counters. */
-       writel(0x8000, port + PORT_DECODE_ERR_THRESH);
-       writel(0x8000, port + PORT_CRC_ERR_THRESH);
-       writel(0x8000, port + PORT_HSHK_ERR_THRESH);
-       writel(0x0000, port + PORT_DECODE_ERR_CNT);
-       writel(0x0000, port + PORT_CRC_ERR_CNT);
-       writel(0x0000, port + PORT_HSHK_ERR_CNT);
+       writew(0x8000, port + PORT_DECODE_ERR_THRESH);
+       writew(0x8000, port + PORT_CRC_ERR_THRESH);
+       writew(0x8000, port + PORT_HSHK_ERR_THRESH);
+       writew(0x0000, port + PORT_DECODE_ERR_CNT);
+       writew(0x0000, port + PORT_CRC_ERR_CNT);
+       writew(0x0000, port + PORT_HSHK_ERR_CNT);
 
        /* always use 64bit activation */
        writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
@@ -622,6 +622,11 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp,
        irq_enabled = readl(port + PORT_IRQ_ENABLE_SET);
        writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR, port + PORT_IRQ_ENABLE_CLR);
 
+       /*
+        * The barrier is required to ensure that writes to cmd_block reach
+        * the memory before the write to PORT_CMD_ACTIVATE.
+        */
+       wmb();
        writel((u32)paddr, port + PORT_CMD_ACTIVATE);
        writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
 
@@ -865,7 +870,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
        } else {
                prb = &cb->atapi.prb;
                sge = cb->atapi.sge;
-               memset(cb->atapi.cdb, 0, 32);
+               memset(cb->atapi.cdb, 0, sizeof(cb->atapi.cdb));
                memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
 
                if (ata_is_data(qc->tf.protocol)) {
@@ -895,6 +900,11 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
        paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block);
        activate = port + PORT_CMD_ACTIVATE + tag * 8;
 
+       /*
+        * The barrier is required to ensure that writes to cmd_block reach
+        * the memory before the write to PORT_CMD_ACTIVATE.
+        */
+       wmb();
        writel((u32)paddr, activate);
        writel((u64)paddr >> 32, activate + 4);
 
index 101d8c219cafede5f3eb3792cd31ab0d9d7fe9e3..4730c42a5ee58c54a295dc6a72e493f7b91cd411 100644 (file)
@@ -575,6 +575,33 @@ static void svia_configure(struct pci_dev *pdev)
                tmp8 |= NATIVE_MODE_ALL;
                pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
        }
+
+       /*
+        * vt6421 has problems talking to some drives.  The following
+        * is the fix from Joseph Chan <JosephChan@via.com.tw>.
+        *
+        * When host issues HOLD, device may send up to 20DW of data
+        * before acknowledging it with HOLDA and the host should be
+        * able to buffer them in FIFO.  Unfortunately, some WD drives
+        * send upto 40DW before acknowledging HOLD and, in the
+        * default configuration, this ends up overflowing vt6421's
+        * FIFO, making the controller abort the transaction with
+        * R_ERR.
+        *
+        * Rx52[2] is the internal 128DW FIFO Flow control watermark
+        * adjusting mechanism enable bit and the default value 0
+        * means host will issue HOLD to device when the left FIFO
+        * size goes below 32DW.  Setting it to 1 makes the watermark
+        * 64DW.
+        *
+        * https://bugzilla.kernel.org/show_bug.cgi?id=15173
+        * http://article.gmane.org/gmane.linux.ide/46352
+        */
+       if (pdev->device == 0x3249) {
+               pci_read_config_byte(pdev, 0x52, &tmp8);
+               tmp8 |= 1 << 2;
+               pci_write_config_byte(pdev, 0x52, tmp8);
+       }
 }
 
 static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
index 6081e81d5738b3fecb90da4350d7325b6b78d28a..f1bf79d9bc0a1c65df988ef4ec0b3c1eab907d93 100644 (file)
@@ -133,6 +133,28 @@ static struct page *brd_insert_page(struct brd_device *brd, sector_t sector)
        return page;
 }
 
+static void brd_free_page(struct brd_device *brd, sector_t sector)
+{
+       struct page *page;
+       pgoff_t idx;
+
+       spin_lock(&brd->brd_lock);
+       idx = sector >> PAGE_SECTORS_SHIFT;
+       page = radix_tree_delete(&brd->brd_pages, idx);
+       spin_unlock(&brd->brd_lock);
+       if (page)
+               __free_page(page);
+}
+
+static void brd_zero_page(struct brd_device *brd, sector_t sector)
+{
+       struct page *page;
+
+       page = brd_lookup_page(brd, sector);
+       if (page)
+               clear_highpage(page);
+}
+
 /*
  * Free all backing store pages and radix tree. This must only be called when
  * there are no other users of the device.
@@ -189,6 +211,24 @@ static int copy_to_brd_setup(struct brd_device *brd, sector_t sector, size_t n)
        return 0;
 }
 
+static void discard_from_brd(struct brd_device *brd,
+                       sector_t sector, size_t n)
+{
+       while (n >= PAGE_SIZE) {
+               /*
+                * Don't want to actually discard pages here because
+                * re-allocating the pages can result in writeback
+                * deadlocks under heavy load.
+                */
+               if (0)
+                       brd_free_page(brd, sector);
+               else
+                       brd_zero_page(brd, sector);
+               sector += PAGE_SIZE >> SECTOR_SHIFT;
+               n -= PAGE_SIZE;
+       }
+}
+
 /*
  * Copy n bytes from src to the brd starting at sector. Does not sleep.
  */
@@ -300,6 +340,12 @@ static int brd_make_request(struct request_queue *q, struct bio *bio)
                                                get_capacity(bdev->bd_disk))
                goto out;
 
+       if (unlikely(bio_rw_flagged(bio, BIO_RW_DISCARD))) {
+               err = 0;
+               discard_from_brd(brd, sector, bio->bi_size);
+               goto out;
+       }
+
        rw = bio_rw(bio);
        if (rw == READA)
                rw = READ;
@@ -320,7 +366,7 @@ out:
 }
 
 #ifdef CONFIG_BLK_DEV_XIP
-static int brd_direct_access (struct block_device *bdev, sector_t sector,
+static int brd_direct_access(struct block_device *bdev, sector_t sector,
                        void **kaddr, unsigned long *pfn)
 {
        struct brd_device *brd = bdev->bd_disk->private_data;
@@ -437,6 +483,11 @@ static struct brd_device *brd_alloc(int i)
        blk_queue_max_hw_sectors(brd->brd_queue, 1024);
        blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY);
 
+       brd->brd_queue->limits.discard_granularity = PAGE_SIZE;
+       brd->brd_queue->limits.max_discard_sectors = UINT_MAX;
+       brd->brd_queue->limits.discard_zeroes_data = 1;
+       queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, brd->brd_queue);
+
        disk = brd->brd_disk = alloc_disk(1 << part_shift);
        if (!disk)
                goto out_free_queue;
index e1d0e2cfec72aaae4d332e693005d5d30833e8ab..72dae92f3cab89770e0c43abd6e7b01aa554b62c 100644 (file)
@@ -188,11 +188,11 @@ scsi_cmd_free(ctlr_info_t *h, CommandList_struct *cmd)
 
        sa = h->scsi_ctlr;
        stk = &sa->cmd_stack; 
+       stk->top++;
        if (stk->top >= CMD_STACK_SIZE) {
                printk("cciss: scsi_cmd_free called too many times.\n");
                BUG();
        }
-       stk->top++;
        stk->elem[stk->top] = (struct cciss_scsi_cmd_stack_elem_t *) cmd;
 }
 
@@ -861,6 +861,7 @@ cciss_scsi_detect(int ctlr)
        sh->n_io_port = 0;      // I don't think we use these two...
        sh->this_id = SELF_SCSI_ID;  
        sh->sg_tablesize = hba[ctlr]->maxsgentries;
+       sh->max_cmd_len = MAX_COMMAND_SIZE;
 
        ((struct cciss_scsi_adapter_data_t *) 
                hba[ctlr]->scsi_ctlr)->scsi_host = sh;
index 91d11631cec96a523f8f7f9504ce6405edba920a..abb4ec6690fcc7b45f96bf8067d96c9e83999ebe 100644 (file)
@@ -386,7 +386,7 @@ static void __devexit cpqarray_remove_one_eisa (int i)
 }
 
 /* pdev is NULL for eisa */
-static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev)
+static int __devinit cpqarray_register_ctlr( int i, struct pci_dev *pdev)
 {
        struct request_queue *q;
        int j;
@@ -503,7 +503,7 @@ Enomem4:
        return -1;
 }
 
-static int __init cpqarray_init_one( struct pci_dev *pdev,
+static int __devinit cpqarray_init_one( struct pci_dev *pdev,
        const struct pci_device_id *ent)
 {
        int i;
@@ -740,7 +740,7 @@ __setup("smart2=", cpqarray_setup);
 /*
  * Find an EISA controller's signature.  Set up an hba if we find it.
  */
-static int __init cpqarray_eisa_detect(void)
+static int __devinit cpqarray_eisa_detect(void)
 {
        int i=0, j;
        __u32 board_id;
index e9654c8d5b6265f5f125c80185bd54b8034b697a..485ed8c7d623986b1aabbcd19ee50768f6c60c4c 100644 (file)
@@ -943,8 +943,7 @@ struct drbd_conf {
        struct drbd_work  resync_work,
                          unplug_work,
                          md_sync_work,
-                         delay_probe_work,
-                         uuid_work;
+                         delay_probe_work;
        struct timer_list resync_timer;
        struct timer_list md_sync_timer;
        struct timer_list delay_probe_timer;
@@ -1069,7 +1068,6 @@ struct drbd_conf {
        struct timeval dps_time; /* delay-probes-start-time */
        unsigned int dp_volume_last;  /* send_cnt of last delay probe */
        int c_sync_rate; /* current resync rate after delay_probe magic */
-       atomic_t new_c_uuid;
 };
 
 static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
@@ -1476,7 +1474,6 @@ extern int w_e_end_ov_req(struct drbd_conf *, struct drbd_work *, int);
 extern int w_ov_finished(struct drbd_conf *, struct drbd_work *, int);
 extern int w_resync_inactive(struct drbd_conf *, struct drbd_work *, int);
 extern int w_resume_next_sg(struct drbd_conf *, struct drbd_work *, int);
-extern int w_io_error(struct drbd_conf *, struct drbd_work *, int);
 extern int w_send_write_hint(struct drbd_conf *, struct drbd_work *, int);
 extern int w_make_resync_request(struct drbd_conf *, struct drbd_work *, int);
 extern int w_send_dblock(struct drbd_conf *, struct drbd_work *, int);
@@ -1542,7 +1539,7 @@ static inline void drbd_tcp_nodelay(struct socket *sock)
 
 static inline void drbd_tcp_quickack(struct socket *sock)
 {
-       int __user val = 1;
+       int __user val = 2;
        (void) drbd_setsockopt(sock, SOL_TCP, TCP_QUICKACK,
                        (char __user *)&val, sizeof(val));
 }
@@ -1728,7 +1725,7 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach,
        switch (mdev->ldev->dc.on_io_error) {
        case EP_PASS_ON:
                if (!forcedetach) {
-                       if (printk_ratelimit())
+                       if (__ratelimit(&drbd_ratelimit_state))
                                dev_err(DEV, "Local IO failed in %s."
                                             "Passing error on...\n", where);
                        break;
@@ -2219,8 +2216,6 @@ static inline int __inc_ap_bio_cond(struct drbd_conf *mdev)
                return 0;
        if (test_bit(BITMAP_IO, &mdev->flags))
                return 0;
-       if (atomic_read(&mdev->new_c_uuid))
-               return 0;
        return 1;
 }
 
@@ -2241,9 +2236,6 @@ static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
         * to avoid races with the reconnect code,
         * we need to atomic_inc within the spinlock. */
 
-       if (atomic_read(&mdev->new_c_uuid) && atomic_add_unless(&mdev->new_c_uuid, -1, 1))
-               drbd_queue_work_front(&mdev->data.work, &mdev->uuid_work);
-
        spin_lock_irq(&mdev->req_lock);
        while (!__inc_ap_bio_cond(mdev)) {
                prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
index be2d2da9cdba41db2c09f8bea3b1d8df0474f24e..7258c95e895e3c3ff7c91bdc3660154d55061413 100644 (file)
@@ -1215,18 +1215,17 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
             ns.pdsk == D_OUTDATED)) {
                if (get_ldev(mdev)) {
                        if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) &&
-                           mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE &&
-                           !atomic_read(&mdev->new_c_uuid))
-                               atomic_set(&mdev->new_c_uuid, 2);
+                           mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
+                               drbd_uuid_new_current(mdev);
+                               drbd_send_uuids(mdev);
+                       }
                        put_ldev(mdev);
                }
        }
 
        if (ns.pdsk < D_INCONSISTENT && get_ldev(mdev)) {
-               /* Diskless peer becomes primary or got connected do diskless, primary peer. */
-               if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0 &&
-                   !atomic_read(&mdev->new_c_uuid))
-                       atomic_set(&mdev->new_c_uuid, 2);
+               if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0)
+                       drbd_uuid_new_current(mdev);
 
                /* D_DISKLESS Peer becomes secondary */
                if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
@@ -1237,8 +1236,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
        /* Last part of the attaching process ... */
        if (ns.conn >= C_CONNECTED &&
            os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
-               kfree(mdev->p_uuid); /* We expect to receive up-to-date UUIDs soon. */
-               mdev->p_uuid = NULL; /* ...to not use the old ones in the mean time */
                drbd_send_sizes(mdev, 0, 0);  /* to start sync... */
                drbd_send_uuids(mdev);
                drbd_send_state(mdev);
@@ -1350,24 +1347,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
        drbd_md_sync(mdev);
 }
 
-static int w_new_current_uuid(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
-{
-       if (get_ldev(mdev)) {
-               if (mdev->ldev->md.uuid[UI_BITMAP] == 0) {
-                       drbd_uuid_new_current(mdev);
-                       if (get_net_conf(mdev)) {
-                               drbd_send_uuids(mdev);
-                               put_net_conf(mdev);
-                       }
-                       drbd_md_sync(mdev);
-               }
-               put_ldev(mdev);
-       }
-       atomic_dec(&mdev->new_c_uuid);
-       wake_up(&mdev->misc_wait);
-
-       return 1;
-}
 
 static int drbd_thread_setup(void *arg)
 {
@@ -2291,9 +2270,9 @@ static int we_should_drop_the_connection(struct drbd_conf *mdev, struct socket *
  * with page_count == 0 or PageSlab.
  */
 static int _drbd_no_send_page(struct drbd_conf *mdev, struct page *page,
-                  int offset, size_t size)
+                  int offset, size_t size, unsigned msg_flags)
 {
-       int sent = drbd_send(mdev, mdev->data.socket, kmap(page) + offset, size, 0);
+       int sent = drbd_send(mdev, mdev->data.socket, kmap(page) + offset, size, msg_flags);
        kunmap(page);
        if (sent == size)
                mdev->send_cnt += size>>9;
@@ -2301,7 +2280,7 @@ static int _drbd_no_send_page(struct drbd_conf *mdev, struct page *page,
 }
 
 static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
-                   int offset, size_t size)
+                   int offset, size_t size, unsigned msg_flags)
 {
        mm_segment_t oldfs = get_fs();
        int sent, ok;
@@ -2314,14 +2293,15 @@ static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
         * __page_cache_release a page that would actually still be referenced
         * by someone, leading to some obscure delayed Oops somewhere else. */
        if (disable_sendpage || (page_count(page) < 1) || PageSlab(page))
-               return _drbd_no_send_page(mdev, page, offset, size);
+               return _drbd_no_send_page(mdev, page, offset, size, msg_flags);
 
+       msg_flags |= MSG_NOSIGNAL;
        drbd_update_congested(mdev);
        set_fs(KERNEL_DS);
        do {
                sent = mdev->data.socket->ops->sendpage(mdev->data.socket, page,
                                                        offset, len,
-                                                       MSG_NOSIGNAL);
+                                                       msg_flags);
                if (sent == -EAGAIN) {
                        if (we_should_drop_the_connection(mdev,
                                                          mdev->data.socket))
@@ -2350,9 +2330,11 @@ static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio)
 {
        struct bio_vec *bvec;
        int i;
+       /* hint all but last page with MSG_MORE */
        __bio_for_each_segment(bvec, bio, i, 0) {
                if (!_drbd_no_send_page(mdev, bvec->bv_page,
-                                    bvec->bv_offset, bvec->bv_len))
+                                    bvec->bv_offset, bvec->bv_len,
+                                    i == bio->bi_vcnt -1 ? 0 : MSG_MORE))
                        return 0;
        }
        return 1;
@@ -2362,12 +2344,13 @@ static int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio)
 {
        struct bio_vec *bvec;
        int i;
+       /* hint all but last page with MSG_MORE */
        __bio_for_each_segment(bvec, bio, i, 0) {
                if (!_drbd_send_page(mdev, bvec->bv_page,
-                                    bvec->bv_offset, bvec->bv_len))
+                                    bvec->bv_offset, bvec->bv_len,
+                                    i == bio->bi_vcnt -1 ? 0 : MSG_MORE))
                        return 0;
        }
-
        return 1;
 }
 
@@ -2375,9 +2358,11 @@ static int _drbd_send_zc_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e)
 {
        struct page *page = e->pages;
        unsigned len = e->size;
+       /* hint all but last page with MSG_MORE */
        page_chain_for_each(page) {
                unsigned l = min_t(unsigned, len, PAGE_SIZE);
-               if (!_drbd_send_page(mdev, page, 0, l))
+               if (!_drbd_send_page(mdev, page, 0, l,
+                               page_chain_next(page) ? MSG_MORE : 0))
                        return 0;
                len -= l;
        }
@@ -2457,11 +2442,11 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
        p.dp_flags = cpu_to_be32(dp_flags);
        set_bit(UNPLUG_REMOTE, &mdev->flags);
        ok = (sizeof(p) ==
-               drbd_send(mdev, mdev->data.socket, &p, sizeof(p), MSG_MORE));
+               drbd_send(mdev, mdev->data.socket, &p, sizeof(p), dgs ? MSG_MORE : 0));
        if (ok && dgs) {
                dgb = mdev->int_dig_out;
                drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, dgb);
-               ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE);
+               ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
        }
        if (ok) {
                if (mdev->net_conf->wire_protocol == DRBD_PROT_A)
@@ -2510,11 +2495,11 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
                return 0;
 
        ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p,
-                                       sizeof(p), MSG_MORE);
+                                       sizeof(p), dgs ? MSG_MORE : 0);
        if (ok && dgs) {
                dgb = mdev->int_dig_out;
                drbd_csum_ee(mdev, mdev->integrity_w_tfm, e, dgb);
-               ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE);
+               ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
        }
        if (ok)
                ok = _drbd_send_zc_ee(mdev, e);
@@ -2708,7 +2693,6 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
        atomic_set(&mdev->net_cnt, 0);
        atomic_set(&mdev->packet_seq, 0);
        atomic_set(&mdev->pp_in_use, 0);
-       atomic_set(&mdev->new_c_uuid, 0);
 
        mutex_init(&mdev->md_io_mutex);
        mutex_init(&mdev->data.mutex);
@@ -2739,14 +2723,12 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
        INIT_LIST_HEAD(&mdev->bm_io_work.w.list);
        INIT_LIST_HEAD(&mdev->delay_probes);
        INIT_LIST_HEAD(&mdev->delay_probe_work.list);
-       INIT_LIST_HEAD(&mdev->uuid_work.list);
 
        mdev->resync_work.cb  = w_resync_inactive;
        mdev->unplug_work.cb  = w_send_write_hint;
        mdev->md_sync_work.cb = w_md_sync;
        mdev->bm_io_work.w.cb = w_bitmap_io;
        mdev->delay_probe_work.cb = w_delay_probes;
-       mdev->uuid_work.cb = w_new_current_uuid;
        init_timer(&mdev->resync_timer);
        init_timer(&mdev->md_sync_timer);
        init_timer(&mdev->delay_probe_timer);
@@ -3799,7 +3781,7 @@ _drbd_insert_fault(struct drbd_conf *mdev, unsigned int type)
        if (ret) {
                fault_count++;
 
-               if (printk_ratelimit())
+               if (__ratelimit(&drbd_ratelimit_state))
                        dev_warn(DEV, "***Simulating %s failure\n",
                                _drbd_fault_str(type));
        }
index 632e3245d1bb2a2f74d01394a4fb55862e30b226..2151f18b21deb27e0d5ecbd369180f12333b3479 100644 (file)
@@ -1114,6 +1114,12 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
                mdev->new_state_tmp.i = ns.i;
                ns.i = os.i;
                ns.disk = D_NEGOTIATING;
+
+               /* We expect to receive up-to-date UUIDs soon.
+                  To avoid a race in receive_state, free p_uuid while
+                  holding req_lock. I.e. atomic with the state change */
+               kfree(mdev->p_uuid);
+               mdev->p_uuid = NULL;
        }
 
        rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
index bc9ab7fb2cc7d6eaeda21fcfa07706cfe5a4c922..dff48701b84d8784f0f85a9202abbaaf16c522fc 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/unistd.h>
 #include <linux/vmalloc.h>
 #include <linux/random.h>
-#include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/scatterlist.h>
 #include "drbd_int.h"
@@ -571,6 +570,25 @@ static int drbd_recv(struct drbd_conf *mdev, void *buf, size_t size)
        return rv;
 }
 
+/* quoting tcp(7):
+ *   On individual connections, the socket buffer size must be set prior to the
+ *   listen(2) or connect(2) calls in order to have it take effect.
+ * This is our wrapper to do so.
+ */
+static void drbd_setbufsize(struct socket *sock, unsigned int snd,
+               unsigned int rcv)
+{
+       /* open coded SO_SNDBUF, SO_RCVBUF */
+       if (snd) {
+               sock->sk->sk_sndbuf = snd;
+               sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
+       }
+       if (rcv) {
+               sock->sk->sk_rcvbuf = rcv;
+               sock->sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
+       }
+}
+
 static struct socket *drbd_try_connect(struct drbd_conf *mdev)
 {
        const char *what;
@@ -592,6 +610,8 @@ static struct socket *drbd_try_connect(struct drbd_conf *mdev)
 
        sock->sk->sk_rcvtimeo =
        sock->sk->sk_sndtimeo =  mdev->net_conf->try_connect_int*HZ;
+       drbd_setbufsize(sock, mdev->net_conf->sndbuf_size,
+                       mdev->net_conf->rcvbuf_size);
 
        /* explicitly bind to the configured IP as source IP
        *  for the outgoing connections.
@@ -670,6 +690,8 @@ static struct socket *drbd_wait_for_connect(struct drbd_conf *mdev)
        s_listen->sk->sk_reuse    = 1; /* SO_REUSEADDR */
        s_listen->sk->sk_rcvtimeo = timeo;
        s_listen->sk->sk_sndtimeo = timeo;
+       drbd_setbufsize(s_listen, mdev->net_conf->sndbuf_size,
+                       mdev->net_conf->rcvbuf_size);
 
        what = "bind before listen";
        err = s_listen->ops->bind(s_listen,
@@ -856,16 +878,6 @@ retry:
        sock->sk->sk_priority = TC_PRIO_INTERACTIVE_BULK;
        msock->sk->sk_priority = TC_PRIO_INTERACTIVE;
 
-       if (mdev->net_conf->sndbuf_size) {
-               sock->sk->sk_sndbuf = mdev->net_conf->sndbuf_size;
-               sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
-       }
-
-       if (mdev->net_conf->rcvbuf_size) {
-               sock->sk->sk_rcvbuf = mdev->net_conf->rcvbuf_size;
-               sock->sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
-       }
-
        /* NOT YET ...
         * sock->sk->sk_sndtimeo = mdev->net_conf->timeout*HZ/10;
         * sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
@@ -1154,17 +1166,6 @@ int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
        unsigned n_bios = 0;
        unsigned nr_pages = (ds + PAGE_SIZE -1) >> PAGE_SHIFT;
 
-       if (atomic_read(&mdev->new_c_uuid)) {
-               if (atomic_add_unless(&mdev->new_c_uuid, -1, 1)) {
-                       drbd_uuid_new_current(mdev);
-                       drbd_md_sync(mdev);
-
-                       atomic_dec(&mdev->new_c_uuid);
-                       wake_up(&mdev->misc_wait);
-               }
-               wait_event(mdev->misc_wait, !atomic_read(&mdev->new_c_uuid));
-       }
-
        /* In most cases, we will only need one bio.  But in case the lower
         * level restrictions happen to be different at this offset on this
         * side than those of the sending peer, we may need to submit the
index 3397f11d0ba915fd29ca9cd6f65717d2f6a83f10..654f1ef5cbb0fb6e21c25430e8e2cace1a84630f 100644 (file)
@@ -102,32 +102,7 @@ static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const
                }
        }
 
-       /* if it was a local io error, we want to notify our
-        * peer about that, and see if we need to
-        * detach the disk and stuff.
-        * to avoid allocating some special work
-        * struct, reuse the request. */
-
-       /* THINK
-        * why do we do this not when we detect the error,
-        * but delay it until it is "done", i.e. possibly
-        * until the next barrier ack? */
-
-       if (rw == WRITE &&
-           ((s & RQ_LOCAL_MASK) && !(s & RQ_LOCAL_OK))) {
-               if (!(req->w.list.next == LIST_POISON1 ||
-                     list_empty(&req->w.list))) {
-                       /* DEBUG ASSERT only; if this triggers, we
-                        * probably corrupt the worker list here */
-                       dev_err(DEV, "req->w.list.next = %p\n", req->w.list.next);
-                       dev_err(DEV, "req->w.list.prev = %p\n", req->w.list.prev);
-               }
-               req->w.cb = w_io_error;
-               drbd_queue_work(&mdev->data.work, &req->w);
-               /* drbd_req_free() is done in w_io_error */
-       } else {
-               drbd_req_free(req);
-       }
+       drbd_req_free(req);
 }
 
 static void queue_barrier(struct drbd_conf *mdev)
@@ -453,9 +428,6 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
                req->rq_state |= RQ_LOCAL_COMPLETED;
                req->rq_state &= ~RQ_LOCAL_PENDING;
 
-               dev_alert(DEV, "Local WRITE failed sec=%llus size=%u\n",
-                     (unsigned long long)req->sector, req->size);
-               /* and now: check how to handle local io error. */
                __drbd_chk_io_error(mdev, FALSE);
                _req_may_be_done(req, m);
                put_ldev(mdev);
@@ -475,22 +447,21 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
                req->rq_state |= RQ_LOCAL_COMPLETED;
                req->rq_state &= ~RQ_LOCAL_PENDING;
 
-               dev_alert(DEV, "Local READ failed sec=%llus size=%u\n",
-                     (unsigned long long)req->sector, req->size);
-               /* _req_mod(req,to_be_send); oops, recursion... */
                D_ASSERT(!(req->rq_state & RQ_NET_MASK));
-               req->rq_state |= RQ_NET_PENDING;
-               inc_ap_pending(mdev);
 
                __drbd_chk_io_error(mdev, FALSE);
                put_ldev(mdev);
-               /* NOTE: if we have no connection,
-                * or know the peer has no good data either,
-                * then we don't actually need to "queue_for_net_read",
-                * but we do so anyways, since the drbd_io_error()
-                * and the potential state change to "Diskless"
-                * needs to be done from process context */
 
+               /* no point in retrying if there is no good remote data,
+                * or we have no connection. */
+               if (mdev->state.pdsk != D_UP_TO_DATE) {
+                       _req_may_be_done(req, m);
+                       break;
+               }
+
+               /* _req_mod(req,to_be_send); oops, recursion... */
+               req->rq_state |= RQ_NET_PENDING;
+               inc_ap_pending(mdev);
                /* fall through: _req_mod(req,queue_for_net_read); */
 
        case queue_for_net_read:
@@ -600,6 +571,9 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
                _req_may_be_done(req, m);
                break;
 
+       case read_retry_remote_canceled:
+               req->rq_state &= ~RQ_NET_QUEUED;
+               /* fall through, in case we raced with drbd_disconnect */
        case connection_lost_while_pending:
                /* transfer log cleanup after connection loss */
                /* assert something? */
index 16119d7056cc65e1eae0e97245eaf7d28f78e884..02d575d245187b301e223cfc8ef5859990a637f6 100644 (file)
@@ -91,6 +91,7 @@ enum drbd_req_event {
        send_failed,
        handed_over_to_network,
        connection_lost_while_pending,
+       read_retry_remote_canceled,
        recv_acked_by_peer,
        write_acked_by_peer,
        write_acked_by_peer_and_sis, /* and set_in_sync */
index 727ff6339754776c389f717ca98276bbdd72714e..b623ceee2a4a6b06a42b9beef06d24f18b28bf71 100644 (file)
@@ -224,9 +224,6 @@ void drbd_endio_pri(struct bio *bio, int error)
        enum drbd_req_event what;
        int uptodate = bio_flagged(bio, BIO_UPTODATE);
 
-       if (error)
-               dev_warn(DEV, "p %s: error=%d\n",
-                        bio_data_dir(bio) == WRITE ? "write" : "read", error);
        if (!error && !uptodate) {
                dev_warn(DEV, "p %s: setting error to -EIO\n",
                         bio_data_dir(bio) == WRITE ? "write" : "read");
@@ -257,20 +254,6 @@ void drbd_endio_pri(struct bio *bio, int error)
                complete_master_bio(mdev, &m);
 }
 
-int w_io_error(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
-{
-       struct drbd_request *req = container_of(w, struct drbd_request, w);
-
-       /* NOTE: mdev->ldev can be NULL by the time we get here! */
-       /* D_ASSERT(mdev->ldev->dc.on_io_error != EP_PASS_ON); */
-
-       /* the only way this callback is scheduled is from _req_may_be_done,
-        * when it is done and had a local write error, see comments there */
-       drbd_req_free(req);
-
-       return TRUE;
-}
-
 int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
 {
        struct drbd_request *req = container_of(w, struct drbd_request, w);
@@ -280,12 +263,9 @@ int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
         * to give the disk the chance to relocate that block */
 
        spin_lock_irq(&mdev->req_lock);
-       if (cancel ||
-           mdev->state.conn < C_CONNECTED ||
-           mdev->state.pdsk <= D_INCONSISTENT) {
-               _req_mod(req, send_canceled);
+       if (cancel || mdev->state.pdsk != D_UP_TO_DATE) {
+               _req_mod(req, read_retry_remote_canceled);
                spin_unlock_irq(&mdev->req_lock);
-               dev_alert(DEV, "WE ARE LOST. Local IO failure, no peer.\n");
                return 1;
        }
        spin_unlock_irq(&mdev->req_lock);
index 52f2d11bc7b975e55c49881f42e49f5552fc4371..ed6fb91123abb67577f6f309f0171a6d7e0cb142 100644 (file)
@@ -1159,8 +1159,10 @@ static struct of_device_id swim3_match[] =
 
 static struct macio_driver swim3_driver =
 {
-       .name           = "swim3",
-       .match_table    = swim3_match,
+       .driver = {
+               .name           = "swim3",
+               .of_match_table = swim3_match,
+       },
        .probe          = swim3_attach,
 #if 0
        .suspend        = swim3_suspend,
index 83fa09a836ca8574a3696c888d7574a833b35447..258bc2ae2885625a1650cebcabb4b9eb975092bb 100644 (file)
@@ -298,7 +298,9 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
        err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
                                offsetof(struct virtio_blk_config, seg_max),
                                &sg_elems);
-       if (err)
+
+       /* We need at least one SG element, whatever they say. */
+       if (err || !sg_elems)
                sg_elems = 1;
 
        /* We need an extra sg elements at head and tail. */
index f09fc0e2062dfdf9b0d2c4d816cd4fada77c4628..7cfcc629a7fd0f89bf56995652aff7d888379549 100644 (file)
@@ -1123,6 +1123,7 @@ source "drivers/s390/char/Kconfig"
 
 config RAMOOPS
        tristate "Log panic/oops to a RAM buffer"
+       depends on HAS_IOMEM
        default n
        help
          This enables panic and oops messages to be logged to a circular
index 4b51982fd23a23a2c2683bfc3dd87dd1abe6af24..d2abf51439836383fd9b03612a44bdf1779448fa 100644 (file)
@@ -97,20 +97,18 @@ EXPORT_SYMBOL(agp_flush_chipset);
 void agp_alloc_page_array(size_t size, struct agp_memory *mem)
 {
        mem->pages = NULL;
-       mem->vmalloc_flag = false;
 
        if (size <= 2*PAGE_SIZE)
-               mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
+               mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
        if (mem->pages == NULL) {
                mem->pages = vmalloc(size);
-               mem->vmalloc_flag = true;
        }
 }
 EXPORT_SYMBOL(agp_alloc_page_array);
 
 void agp_free_page_array(struct agp_memory *mem)
 {
-       if (mem->vmalloc_flag) {
+       if (is_vmalloc_addr(mem->pages)) {
                vfree(mem->pages);
        } else {
                kfree(mem->pages);
index e8ea6825822ce8ccb04f25a444c7880b1b6da170..9344216183a433a84210b5ebaef0efd57e6aa9c7 100644 (file)
@@ -1059,7 +1059,7 @@ static void intel_i9xx_setup_flush(void)
        }
 }
 
-static int intel_i915_configure(void)
+static int intel_i9xx_configure(void)
 {
        struct aper_size_info_fixed *current_size;
        u32 temp;
@@ -1207,6 +1207,38 @@ static int intel_i9xx_fetch_size(void)
        return 0;
 }
 
+static int intel_i915_get_gtt_size(void)
+{
+       int size;
+
+       if (IS_G33) {
+               u16 gmch_ctrl;
+
+               /* G33's GTT size defined in gmch_ctrl */
+               pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
+               switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
+               case G33_PGETBL_SIZE_1M:
+                       size = 1024;
+                       break;
+               case G33_PGETBL_SIZE_2M:
+                       size = 2048;
+                       break;
+               default:
+                       dev_info(&agp_bridge->dev->dev,
+                                "unknown page table size 0x%x, assuming 512KB\n",
+                               (gmch_ctrl & G33_PGETBL_SIZE_MASK));
+                       size = 512;
+               }
+       } else {
+               /* On previous hardware, the GTT size was just what was
+                * required to map the aperture.
+                */
+               size = agp_bridge->driver->fetch_size();
+       }
+
+       return KB(size);
+}
+
 /* The intel i915 automatically initializes the agp aperture during POST.
  * Use the memory already set aside for in the GTT.
  */
@@ -1216,7 +1248,7 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
        struct aper_size_info_fixed *size;
        int num_entries;
        u32 temp, temp2;
-       int gtt_map_size = 256 * 1024;
+       int gtt_map_size;
 
        size = agp_bridge->current_size;
        page_order = size->page_order;
@@ -1226,8 +1258,8 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
        pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
        pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2);
 
-       if (IS_G33)
-           gtt_map_size = 1024 * 1024; /* 1M on G33 */
+       gtt_map_size = intel_i915_get_gtt_size();
+
        intel_private.gtt = ioremap(temp2, gtt_map_size);
        if (!intel_private.gtt)
                return -ENOMEM;
@@ -1422,7 +1454,7 @@ static const struct agp_bridge_driver intel_915_driver = {
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
-       .configure              = intel_i915_configure,
+       .configure              = intel_i9xx_configure,
        .fetch_size             = intel_i9xx_fetch_size,
        .cleanup                = intel_i915_cleanup,
        .mask_memory            = intel_i810_mask_memory,
@@ -1455,7 +1487,7 @@ static const struct agp_bridge_driver intel_i965_driver = {
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
-       .configure              = intel_i915_configure,
+       .configure              = intel_i9xx_configure,
        .fetch_size             = intel_i9xx_fetch_size,
        .cleanup                = intel_i915_cleanup,
        .mask_memory            = intel_i965_mask_memory,
@@ -1488,7 +1520,7 @@ static const struct agp_bridge_driver intel_g33_driver = {
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
-       .configure              = intel_i915_configure,
+       .configure              = intel_i9xx_configure,
        .fetch_size             = intel_i9xx_fetch_size,
        .cleanup                = intel_i915_cleanup,
        .mask_memory            = intel_i965_mask_memory,
index 95db71360d2416b437c0447c7ffd64b582ff6b5b..f845a8f718b39af2bd1277e331d50143e24ae9fc 100644 (file)
@@ -415,7 +415,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
        bridge->gatt_table_real = (u32 *) table;
        /* Need to clear out any dirty data still sitting in caches */
        flush_dcache_range((unsigned long)table,
-                          (unsigned long)(table_end + PAGE_SIZE));
+                          (unsigned long)table_end + 1);
        bridge->gatt_table = vmap(pages, (1 << page_order), 0, PAGE_KERNEL_NCG);
 
        if (bridge->gatt_table == NULL)
index 35603dd4e6c5276911dec0b3a11464a152beb8a5..094bdc355b1fe753c003d30277fbf9a038281444 100644 (file)
@@ -302,6 +302,12 @@ struct smi_info {
 
 static int force_kipmid[SI_MAX_PARMS];
 static int num_force_kipmid;
+#ifdef CONFIG_PCI
+static int pci_registered;
+#endif
+#ifdef CONFIG_PPC_OF
+static int of_registered;
+#endif
 
 static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];
 static int num_max_busy_us;
@@ -1018,7 +1024,7 @@ static int ipmi_thread(void *data)
                else if (smi_result == SI_SM_IDLE)
                        schedule_timeout_interruptible(100);
                else
-                       schedule_timeout_interruptible(0);
+                       schedule_timeout_interruptible(1);
        }
        return 0;
 }
@@ -3314,6 +3320,8 @@ static __devinit int init_ipmi_si(void)
        rv = pci_register_driver(&ipmi_pci_driver);
        if (rv)
                printk(KERN_ERR PFX "Unable to register PCI driver: %d\n", rv);
+       else
+               pci_registered = 1;
 #endif
 
 #ifdef CONFIG_ACPI
@@ -3330,6 +3338,7 @@ static __devinit int init_ipmi_si(void)
 
 #ifdef CONFIG_PPC_OF
        of_register_platform_driver(&ipmi_of_platform_driver);
+       of_registered = 1;
 #endif
 
        /* We prefer devices with interrupts, but in the case of a machine
@@ -3383,11 +3392,13 @@ static __devinit int init_ipmi_si(void)
        if (unload_when_empty && list_empty(&smi_infos)) {
                mutex_unlock(&smi_infos_lock);
 #ifdef CONFIG_PCI
-               pci_unregister_driver(&ipmi_pci_driver);
+               if (pci_registered)
+                       pci_unregister_driver(&ipmi_pci_driver);
 #endif
 
 #ifdef CONFIG_PPC_OF
-               of_unregister_platform_driver(&ipmi_of_platform_driver);
+               if (of_registered)
+                       of_unregister_platform_driver(&ipmi_of_platform_driver);
 #endif
                driver_unregister(&ipmi_driver.driver);
                printk(KERN_WARNING PFX
@@ -3478,14 +3489,16 @@ static __exit void cleanup_ipmi_si(void)
                return;
 
 #ifdef CONFIG_PCI
-       pci_unregister_driver(&ipmi_pci_driver);
+       if (pci_registered)
+               pci_unregister_driver(&ipmi_pci_driver);
 #endif
 #ifdef CONFIG_ACPI
        pnp_unregister_driver(&ipmi_pnp_driver);
 #endif
 
 #ifdef CONFIG_PPC_OF
-       of_unregister_platform_driver(&ipmi_of_platform_driver);
+       if (of_registered)
+               of_unregister_platform_driver(&ipmi_of_platform_driver);
 #endif
 
        mutex_lock(&smi_infos_lock);
index c4161d5e053d383c74d79905dfdb8d3fef27868e..e4089c432f15fea5964418cdf8d765e47f39bb50 100644 (file)
@@ -904,9 +904,7 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm)
        int len;
        /* Priority ordering: We should do priority with RR of the groups */
        int i = 1;
-       unsigned long flags;
 
-       spin_lock_irqsave(&gsm->tx_lock, flags);
        while (i < NUM_DLCI) {
                struct gsm_dlci *dlci;
 
@@ -927,7 +925,6 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm)
                if (len == 0)
                        i++;
        }
-       spin_unlock_irqrestore(&gsm->tx_lock, flags);
 }
 
 /**
@@ -2230,12 +2227,16 @@ static int gsmld_open(struct tty_struct *tty)
 static void gsmld_write_wakeup(struct tty_struct *tty)
 {
        struct gsm_mux *gsm = tty->disc_data;
+       unsigned long flags;
 
        /* Queue poll */
        clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
        gsm_data_kick(gsm);
-       if (gsm->tx_bytes < TX_THRESH_LO)
+       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);
+       }
 }
 
 /**
index 5d15630a5830944ad131b7cc83240e434dfe7c0e..5d64e3acb000ef62b08921d7f946f9fdfc2d2182 100644 (file)
@@ -580,8 +580,12 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type,
        case KEY_RIGHTALT:
                if (value)
                        sysrq_alt = code;
-               else if (sysrq_down && code == sysrq_alt_use)
-                       sysrq_down = false;
+               else {
+                       if (sysrq_down && code == sysrq_alt_use)
+                               sysrq_down = false;
+
+                       sysrq_alt = 0;
+               }
                break;
 
        case KEY_SYSRQ:
index 8e00b4ddd0830699bca8bab65c3e855657b21978..792868d24f2a0f2ad6bc21a4967ace01a2f84d92 100644 (file)
@@ -224,6 +224,7 @@ struct      tpm_readpubek_params_out {
        u8      algorithm[4];
        u8      encscheme[2];
        u8      sigscheme[2];
+       __be32  paramsize;
        u8      parameters[12]; /*assuming RSA*/
        __be32  keysize;
        u8      modulus[256];
index 8c99bf1b5e9fde218dab95f2091b807a7fbb4623..942a9826bd23ed64b83095fcdeb65ed059c9ce02 100644 (file)
@@ -529,6 +529,10 @@ static bool will_write_block(struct port *port)
 {
        bool ret;
 
+       if (!port->guest_connected) {
+               /* Port got hot-unplugged. Let's exit. */
+               return false;
+       }
        if (!port->host_connected)
                return true;
 
@@ -1099,6 +1103,13 @@ static int remove_port(struct port *port)
 {
        struct port_buffer *buf;
 
+       if (port->guest_connected) {
+               port->guest_connected = false;
+               port->host_connected = false;
+               wake_up_interruptible(&port->waitqueue);
+               send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
+       }
+
        spin_lock_irq(&port->portdev->ports_lock);
        list_del(&port->list);
        spin_unlock_irq(&port->portdev->ports_lock);
@@ -1120,9 +1131,6 @@ static int remove_port(struct port *port)
                hvc_remove(port->cons.hvc);
 #endif
        }
-       if (port->guest_connected)
-               send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
-
        sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
        device_destroy(pdrvdata.class, port->dev->devt);
        cdev_del(&port->cdev);
index 6aa10284104aeb6e4bc3a22833ea347e67c5d976..cb19dbc52136426d3b869c089a7153de2c719c7f 100644 (file)
@@ -1303,7 +1303,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                if (!perm)
                        goto eperm;
                ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
-               if (!ret)
+               if (ret)
+                       ret = -EFAULT;
+               else
                        con_clear_unimap(vc, &ui);
                break;
              }
index f6677cb197895e51bd1c2ddb1a1cdc886980aec5..717305d30444479d67130194a7f922173254da75 100644 (file)
@@ -412,18 +412,10 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
 static int sh_cmt_clocksource_enable(struct clocksource *cs)
 {
        struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
-       int ret;
 
        p->total_cycles = 0;
 
-       ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
-       if (ret)
-               return ret;
-
-       /* TODO: calculate good shift from rate and counter bit width */
-       cs->shift = 0;
-       cs->mult = clocksource_hz2mult(p->rate, cs->shift);
-       return 0;
+       return sh_cmt_start(p, FLAG_CLOCKSOURCE);
 }
 
 static void sh_cmt_clocksource_disable(struct clocksource *cs)
@@ -450,8 +442,20 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
        cs->resume = sh_cmt_clocksource_resume;
        cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
        cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+       /* clk_get_rate() needs an enabled clock */
+       clk_enable(p->clk);
+       p->rate = clk_get_rate(p->clk) / (p->width == 16) ? 512 : 8;
+       clk_disable(p->clk);
+
+       /* TODO: calculate good shift from rate and counter bit width */
+       cs->shift = 0;
+       cs->mult = clocksource_hz2mult(p->rate, cs->shift);
+
        dev_info(&p->pdev->dev, "used as clock source\n");
+
        clocksource_register(cs);
+
        return 0;
 }
 
index 8e44e14ec4c2dffdb214261edbcf4f2ea9fd60a3..de715901b82a28a09f8160dd1b62f17a25247a51 100644 (file)
@@ -199,16 +199,8 @@ static cycle_t sh_tmu_clocksource_read(struct clocksource *cs)
 static int sh_tmu_clocksource_enable(struct clocksource *cs)
 {
        struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
-       int ret;
-
-       ret = sh_tmu_enable(p);
-       if (ret)
-               return ret;
 
-       /* TODO: calculate good shift from rate and counter bit width */
-       cs->shift = 10;
-       cs->mult = clocksource_hz2mult(p->rate, cs->shift);
-       return 0;
+       return sh_tmu_enable(p);
 }
 
 static void sh_tmu_clocksource_disable(struct clocksource *cs)
@@ -228,6 +220,16 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
        cs->disable = sh_tmu_clocksource_disable;
        cs->mask = CLOCKSOURCE_MASK(32);
        cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+       /* clk_get_rate() needs an enabled clock */
+       clk_enable(p->clk);
+       /* channel will be configured at parent clock / 4 */
+       p->rate = clk_get_rate(p->clk) / 4;
+       clk_disable(p->clk);
+       /* TODO: calculate good shift from rate and counter bit width */
+       cs->shift = 10;
+       cs->mult = clocksource_hz2mult(p->rate, cs->shift);
+
        dev_info(&p->pdev->dev, "used as clock source\n");
        clocksource_register(cs);
        return 0;
index 52ff8aa63f8449b04d5bcd046b028e23dcf6d68b..1b128702d300bc5a07ba7ec09f03ec83f3b11b43 100644 (file)
@@ -143,7 +143,7 @@ static inline int which_bucket(unsigned int duration)
         * This allows us to calculate
         * E(duration)|iowait
         */
-       if (nr_iowait_cpu())
+       if (nr_iowait_cpu(smp_processor_id()))
                bucket = BUCKETS/2;
 
        if (duration < 10)
@@ -175,7 +175,7 @@ static inline int performance_multiplier(void)
        mult += 2 * get_loadavg();
 
        /* for IO wait tasks (per cpu!) we add 5x each */
-       mult += 10 * nr_iowait_cpu();
+       mult += 10 * nr_iowait_cpu(smp_processor_id());
 
        return mult;
 }
index 9d65b371de64cced72bcb0f1e483913962277552..983530ba04a7e932c3a70ec692e719fe44cccb21 100644 (file)
@@ -1158,7 +1158,7 @@ static int __init crypto4xx_probe(struct of_device *ofdev,
        struct device *dev = &ofdev->dev;
        struct crypto4xx_core_device *core_dev;
 
-       rc = of_address_to_resource(ofdev->node, 0, &res);
+       rc = of_address_to_resource(ofdev->dev.of_node, 0, &res);
        if (rc)
                return -ENODEV;
 
@@ -1215,13 +1215,13 @@ static int __init crypto4xx_probe(struct of_device *ofdev,
                     (unsigned long) dev);
 
        /* Register for Crypto isr, Crypto Engine IRQ */
-       core_dev->irq = irq_of_parse_and_map(ofdev->node, 0);
+       core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
        rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0,
                         core_dev->dev->name, dev);
        if (rc)
                goto err_request_irq;
 
-       core_dev->dev->ce_base = of_iomap(ofdev->node, 0);
+       core_dev->dev->ce_base = of_iomap(ofdev->dev.of_node, 0);
        if (!core_dev->dev->ce_base) {
                dev_err(dev, "failed to of_iomap\n");
                goto err_iomap;
index 8566be832f5172b7fab29ccf134442d109681170..23163fda5035357a50c892c1a65a35e7ae3a89ea 100644 (file)
@@ -251,16 +251,10 @@ static void n2_base_ctx_init(struct n2_base_ctx *ctx)
 struct n2_hash_ctx {
        struct n2_base_ctx              base;
 
-       struct crypto_ahash             *fallback;
+       struct crypto_ahash             *fallback_tfm;
+};
 
-       /* These next three members must match the layout created by
-        * crypto_init_shash_ops_async.  This allows us to properly
-        * plumb requests we can't do in hardware down to the fallback
-        * operation, providing all of the data structures and layouts
-        * expected by those paths.
-        */
-       struct ahash_request            fallback_req;
-       struct shash_desc               fallback_desc;
+struct n2_hash_req_ctx {
        union {
                struct md5_state        md5;
                struct sha1_state       sha1;
@@ -269,56 +263,62 @@ struct n2_hash_ctx {
 
        unsigned char                   hash_key[64];
        unsigned char                   keyed_zero_hash[32];
+
+       struct ahash_request            fallback_req;
 };
 
 static int n2_hash_async_init(struct ahash_request *req)
 {
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
        struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
 
-       ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
-       ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+       ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+       rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
 
-       return crypto_ahash_init(&ctx->fallback_req);
+       return crypto_ahash_init(&rctx->fallback_req);
 }
 
 static int n2_hash_async_update(struct ahash_request *req)
 {
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
        struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
 
-       ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
-       ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
-       ctx->fallback_req.nbytes = req->nbytes;
-       ctx->fallback_req.src = req->src;
+       ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+       rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+       rctx->fallback_req.nbytes = req->nbytes;
+       rctx->fallback_req.src = req->src;
 
-       return crypto_ahash_update(&ctx->fallback_req);
+       return crypto_ahash_update(&rctx->fallback_req);
 }
 
 static int n2_hash_async_final(struct ahash_request *req)
 {
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
        struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
 
-       ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
-       ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
-       ctx->fallback_req.result = req->result;
+       ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+       rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+       rctx->fallback_req.result = req->result;
 
-       return crypto_ahash_final(&ctx->fallback_req);
+       return crypto_ahash_final(&rctx->fallback_req);
 }
 
 static int n2_hash_async_finup(struct ahash_request *req)
 {
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
        struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
 
-       ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
-       ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
-       ctx->fallback_req.nbytes = req->nbytes;
-       ctx->fallback_req.src = req->src;
-       ctx->fallback_req.result = req->result;
+       ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+       rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+       rctx->fallback_req.nbytes = req->nbytes;
+       rctx->fallback_req.src = req->src;
+       rctx->fallback_req.result = req->result;
 
-       return crypto_ahash_finup(&ctx->fallback_req);
+       return crypto_ahash_finup(&rctx->fallback_req);
 }
 
 static int n2_hash_cra_init(struct crypto_tfm *tfm)
@@ -338,7 +338,10 @@ static int n2_hash_cra_init(struct crypto_tfm *tfm)
                goto out;
        }
 
-       ctx->fallback = fallback_tfm;
+       crypto_ahash_set_reqsize(ahash, (sizeof(struct n2_hash_req_ctx) +
+                                        crypto_ahash_reqsize(fallback_tfm)));
+
+       ctx->fallback_tfm = fallback_tfm;
        return 0;
 
 out:
@@ -350,7 +353,7 @@ static void n2_hash_cra_exit(struct crypto_tfm *tfm)
        struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
        struct n2_hash_ctx *ctx = crypto_ahash_ctx(ahash);
 
-       crypto_free_ahash(ctx->fallback);
+       crypto_free_ahash(ctx->fallback_tfm);
 }
 
 static unsigned long wait_for_tail(struct spu_queue *qp)
@@ -399,14 +402,16 @@ static int n2_hash_async_digest(struct ahash_request *req,
         * exceed 2^16.
         */
        if (unlikely(req->nbytes > (1 << 16))) {
-               ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
-               ctx->fallback_req.base.flags =
+               struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+
+               ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+               rctx->fallback_req.base.flags =
                        req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
-               ctx->fallback_req.nbytes = req->nbytes;
-               ctx->fallback_req.src = req->src;
-               ctx->fallback_req.result = req->result;
+               rctx->fallback_req.nbytes = req->nbytes;
+               rctx->fallback_req.src = req->src;
+               rctx->fallback_req.result = req->result;
 
-               return crypto_ahash_digest(&ctx->fallback_req);
+               return crypto_ahash_digest(&rctx->fallback_req);
        }
 
        n2_base_ctx_init(&ctx->base);
@@ -472,9 +477,8 @@ out:
 
 static int n2_md5_async_digest(struct ahash_request *req)
 {
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct md5_state *m = &ctx->u.md5;
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+       struct md5_state *m = &rctx->u.md5;
 
        if (unlikely(req->nbytes == 0)) {
                static const char md5_zero[MD5_DIGEST_SIZE] = {
@@ -497,9 +501,8 @@ static int n2_md5_async_digest(struct ahash_request *req)
 
 static int n2_sha1_async_digest(struct ahash_request *req)
 {
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct sha1_state *s = &ctx->u.sha1;
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+       struct sha1_state *s = &rctx->u.sha1;
 
        if (unlikely(req->nbytes == 0)) {
                static const char sha1_zero[SHA1_DIGEST_SIZE] = {
@@ -524,9 +527,8 @@ static int n2_sha1_async_digest(struct ahash_request *req)
 
 static int n2_sha256_async_digest(struct ahash_request *req)
 {
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct sha256_state *s = &ctx->u.sha256;
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+       struct sha256_state *s = &rctx->u.sha256;
 
        if (req->nbytes == 0) {
                static const char sha256_zero[SHA256_DIGEST_SIZE] = {
@@ -555,9 +557,8 @@ static int n2_sha256_async_digest(struct ahash_request *req)
 
 static int n2_sha224_async_digest(struct ahash_request *req)
 {
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct sha256_state *s = &ctx->u.sha256;
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+       struct sha256_state *s = &rctx->u.sha256;
 
        if (req->nbytes == 0) {
                static const char sha224_zero[SHA224_DIGEST_SIZE] = {
@@ -1398,7 +1399,7 @@ static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip,
 
        intr = ip->ino_table[i].intr;
 
-       dev_intrs = of_get_property(dev->node, "interrupts", NULL);
+       dev_intrs = of_get_property(dev->dev.of_node, "interrupts", NULL);
        if (!dev_intrs)
                return -ENODEV;
 
@@ -1449,7 +1450,7 @@ static int queue_cache_init(void)
 {
        if (!queue_cache[HV_NCS_QTYPE_MAU - 1])
                queue_cache[HV_NCS_QTYPE_MAU - 1] =
-                       kmem_cache_create("cwq_queue",
+                       kmem_cache_create("mau_queue",
                                          (MAU_NUM_ENTRIES *
                                           MAU_ENTRY_SIZE),
                                          MAU_ENTRY_SIZE, 0, NULL);
@@ -1574,7 +1575,7 @@ static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc,
                id = mdesc_get_property(mdesc, tgt, "id", NULL);
                if (table[*id] != NULL) {
                        dev_err(&dev->dev, "%s: SPU cpu slot already set.\n",
-                               dev->node->full_name);
+                               dev->dev.of_node->full_name);
                        return -EINVAL;
                }
                cpu_set(*id, p->sharing);
@@ -1595,7 +1596,7 @@ static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list,
        p = kzalloc(sizeof(struct spu_queue), GFP_KERNEL);
        if (!p) {
                dev_err(&dev->dev, "%s: Could not allocate SPU queue.\n",
-                       dev->node->full_name);
+                       dev->dev.of_node->full_name);
                return -ENOMEM;
        }
 
@@ -1684,7 +1685,7 @@ static int __devinit grab_mdesc_irq_props(struct mdesc_handle *mdesc,
        const unsigned int *reg;
        u64 node;
 
-       reg = of_get_property(dev->node, "reg", NULL);
+       reg = of_get_property(dev->dev.of_node, "reg", NULL);
        if (!reg)
                return -ENODEV;
 
@@ -1836,7 +1837,7 @@ static int __devinit n2_crypto_probe(struct of_device *dev,
 
        n2_spu_driver_version();
 
-       full_name = dev->node->full_name;
+       full_name = dev->dev.of_node->full_name;
        pr_info("Found N2CP at %s\n", full_name);
 
        np = alloc_n2cp();
@@ -1948,7 +1949,7 @@ static int __devinit n2_mau_probe(struct of_device *dev,
 
        n2_spu_driver_version();
 
-       full_name = dev->node->full_name;
+       full_name = dev->dev.of_node->full_name;
        pr_info("Found NCP at %s\n", full_name);
 
        mp = alloc_ncp();
@@ -2034,8 +2035,11 @@ static struct of_device_id n2_crypto_match[] = {
 MODULE_DEVICE_TABLE(of, n2_crypto_match);
 
 static struct of_platform_driver n2_crypto_driver = {
-       .name           =       "n2cp",
-       .match_table    =       n2_crypto_match,
+       .driver = {
+               .name           =       "n2cp",
+               .owner          =       THIS_MODULE,
+               .of_match_table =       n2_crypto_match,
+       },
        .probe          =       n2_crypto_probe,
        .remove         =       __devexit_p(n2_crypto_remove),
 };
@@ -2055,8 +2059,11 @@ static struct of_device_id n2_mau_match[] = {
 MODULE_DEVICE_TABLE(of, n2_mau_match);
 
 static struct of_platform_driver n2_mau_driver = {
-       .name           =       "ncp",
-       .match_table    =       n2_mau_match,
+       .driver = {
+               .name           =       "ncp",
+               .owner          =       THIS_MODULE,
+               .of_match_table =       n2_mau_match,
+       },
        .probe          =       n2_mau_probe,
        .remove         =       __devexit_p(n2_mau_remove),
 };
index 201e6e19c344d1cfe1ca2ff7402027bf6ca3ba54..14a8c0f1698e4fd1c5e33e33b6f28244741273be 100644 (file)
@@ -630,7 +630,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
 static int __devinit mpc_dma_probe(struct of_device *op,
                                        const struct of_device_id *match)
 {
-       struct device_node *dn = op->node;
+       struct device_node *dn = op->dev.of_node;
        struct device *dev = &op->dev;
        struct dma_device *dma;
        struct mpc_dma *mdma;
@@ -771,12 +771,12 @@ static struct of_device_id mpc_dma_match[] = {
 };
 
 static struct of_platform_driver mpc_dma_driver = {
-       .match_table    = mpc_dma_match,
        .probe          = mpc_dma_probe,
        .remove         = __devexit_p(mpc_dma_remove),
-       .driver         = {
-               .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = mpc_dma_match,
        },
 };
 
index fa98abe4686fb06598c6f8b318e4866dff1f41be..7c3747902a37ad29f7a1031dd7039c69556d3ea3 100644 (file)
@@ -4257,10 +4257,12 @@ static int ppc440spe_adma_setup_irqs(struct ppc440spe_adma_device *adev,
                                     struct ppc440spe_adma_chan *chan,
                                     int *initcode)
 {
+       struct of_device *ofdev;
        struct device_node *np;
        int ret;
 
-       np = container_of(adev->dev, struct of_device, dev)->node;
+       ofdev = container_of(adev->dev, struct of_device, dev);
+       np = ofdev->dev.of_node;
        if (adev->id != PPC440SPE_XOR_ID) {
                adev->err_irq = irq_of_parse_and_map(np, 1);
                if (adev->err_irq == NO_IRQ) {
@@ -4394,7 +4396,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev,
 static int __devinit ppc440spe_adma_probe(struct of_device *ofdev,
                                          const struct of_device_id *match)
 {
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct resource res;
        struct ppc440spe_adma_device *adev;
        struct ppc440spe_adma_chan *chan;
@@ -4626,7 +4628,7 @@ out:
 static int __devexit ppc440spe_adma_remove(struct of_device *ofdev)
 {
        struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev);
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct resource res;
        struct dma_chan *chan, *_chan;
        struct ppc_dma_chan_ref *ref, *_ref;
index 55c9c59b3f713c0f29b211f89806f321fcffc879..aedef7941b22855f17c892f73d370ae10f17632c 100644 (file)
@@ -69,6 +69,9 @@ config EDAC_MM_EDAC
          occurred so that a particular failing memory module can be
          replaced.  If unsure, select 'Y'.
 
+config EDAC_MCE
+       bool
+
 config EDAC_AMD64
        tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
        depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
@@ -166,6 +169,16 @@ config EDAC_I5400
          Support for error detection and correction the Intel
          i5400 MCH chipset (Seaburg).
 
+config EDAC_I7CORE
+       tristate "Intel i7 Core (Nehalem) processors"
+       depends on EDAC_MM_EDAC && PCI && X86
+       select EDAC_MCE
+       help
+         Support for error detection and correction the Intel
+         i7 Core (Nehalem) Integrated Memory Controller that exists on
+         newer processors like i7 Core, i7 Core Extreme, Xeon 35xx
+         and Xeon 55xx processors.
+
 config EDAC_I82860
        tristate "Intel 82860"
        depends on EDAC_MM_EDAC && PCI && X86_32
index bc5dc232a0fbf046b15a28ce069d232aa11fb2b2..ca6b1bb24ccc8e76109b13f38e1237eec98ec09e 100644 (file)
@@ -8,6 +8,7 @@
 
 obj-$(CONFIG_EDAC)                     := edac_stub.o
 obj-$(CONFIG_EDAC_MM_EDAC)             += edac_core.o
+obj-$(CONFIG_EDAC_MCE)                 += edac_mce.o
 
 edac_core-objs := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
 edac_core-objs += edac_module.o edac_device_sysfs.o
@@ -23,6 +24,7 @@ obj-$(CONFIG_EDAC_CPC925)             += cpc925_edac.o
 obj-$(CONFIG_EDAC_I5000)               += i5000_edac.o
 obj-$(CONFIG_EDAC_I5100)               += i5100_edac.o
 obj-$(CONFIG_EDAC_I5400)               += i5400_edac.o
+obj-$(CONFIG_EDAC_I7CORE)              += i7core_edac.o
 obj-$(CONFIG_EDAC_E7XXX)               += e7xxx_edac.o
 obj-$(CONFIG_EDAC_E752X)               += e752x_edac.o
 obj-$(CONFIG_EDAC_I82443BXGX)          += i82443bxgx_edac.o
index cf17dbb8014f75bb0f5109c0008dda9f7c2a27cd..ac9f7985096db06f83302ada4bed9601c7287657 100644 (file)
@@ -1958,20 +1958,20 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome)
        u32 value = 0;
        int err_sym = 0;
 
-       amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value);
+       if (boot_cpu_data.x86 == 0x10) {
 
-       /* F3x180[EccSymbolSize]=1, x8 symbols */
-       if (boot_cpu_data.x86 == 0x10 &&
-           boot_cpu_data.x86_model > 7 &&
-           value & BIT(25)) {
-               err_sym = decode_syndrome(syndrome, x8_vectors,
-                                         ARRAY_SIZE(x8_vectors), 8);
-               return map_err_sym_to_channel(err_sym, 8);
-       } else {
-               err_sym = decode_syndrome(syndrome, x4_vectors,
-                                         ARRAY_SIZE(x4_vectors), 4);
-               return map_err_sym_to_channel(err_sym, 4);
+               amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value);
+
+               /* F3x180[EccSymbolSize]=1 => x8 symbols */
+               if (boot_cpu_data.x86_model > 7 &&
+                   value & BIT(25)) {
+                       err_sym = decode_syndrome(syndrome, x8_vectors,
+                                                 ARRAY_SIZE(x8_vectors), 8);
+                       return map_err_sym_to_channel(err_sym, 8);
+               }
        }
+       err_sym = decode_syndrome(syndrome, x4_vectors, ARRAY_SIZE(x4_vectors), 4);
+       return map_err_sym_to_channel(err_sym, 4);
 }
 
 /*
index 001b2e797fb383a3c4f43f805a160d2bffc3b9d6..efca9343d26a7537df0c2a9a4a6eb546cc58cab3 100644 (file)
@@ -341,12 +341,30 @@ struct csrow_info {
        struct channel_info *channels;
 };
 
+struct mcidev_sysfs_group {
+       const char *name;                               /* group name */
+       struct mcidev_sysfs_attribute *mcidev_attr;     /* group attributes */
+};
+
+struct mcidev_sysfs_group_kobj {
+       struct list_head list;          /* list for all instances within a mc */
+
+       struct kobject kobj;            /* kobj for the group */
+
+       struct mcidev_sysfs_group *grp; /* group description table */
+       struct mem_ctl_info *mci;       /* the parent */
+};
+
 /* mcidev_sysfs_attribute structure
  *     used for driver sysfs attributes and in mem_ctl_info
  *     sysfs top level entries
  */
 struct mcidev_sysfs_attribute {
-        struct attribute attr;
+       /* It should use either attr or grp */
+       struct attribute attr;
+       struct mcidev_sysfs_group *grp; /* Points to a group of attributes */
+
+       /* Ops for show/store values at the attribute - not used on group */
         ssize_t (*show)(struct mem_ctl_info *,char *);
         ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
 };
@@ -424,6 +442,9 @@ struct mem_ctl_info {
        /* edac sysfs device control */
        struct kobject edac_mci_kobj;
 
+       /* list for all grp instances within a mc */
+       struct list_head grp_kobj_list;
+
        /* Additional top controller level attributes, but specified
         * by the low level driver.
         *
index 418b65f1a1da858c5b127c863ced032f773424e1..c200c2fd43ea48d7d6e1e466a0150fe9e443885e 100644 (file)
@@ -557,6 +557,8 @@ static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
        struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
        struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
 
+       debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
+
        if (mcidev_attr->show)
                return mcidev_attr->show(mem_ctl_info, buffer);
 
@@ -569,6 +571,8 @@ static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
        struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
        struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
 
+       debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
+
        if (mcidev_attr->store)
                return mcidev_attr->store(mem_ctl_info, buffer, count);
 
@@ -726,28 +730,118 @@ void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
 
 #define EDAC_DEVICE_SYMLINK    "device"
 
+#define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group_kobj, kobj)->mci)
+
+/* MCI show/store functions for top most object */
+static ssize_t inst_grp_show(struct kobject *kobj, struct attribute *attr,
+                       char *buffer)
+{
+       struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj);
+       struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
+
+       debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
+
+       if (mcidev_attr->show)
+               return mcidev_attr->show(mem_ctl_info, buffer);
+
+       return -EIO;
+}
+
+static ssize_t inst_grp_store(struct kobject *kobj, struct attribute *attr,
+                       const char *buffer, size_t count)
+{
+       struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj);
+       struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
+
+       debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
+
+       if (mcidev_attr->store)
+               return mcidev_attr->store(mem_ctl_info, buffer, count);
+
+       return -EIO;
+}
+
+/* No memory to release for this kobj */
+static void edac_inst_grp_release(struct kobject *kobj)
+{
+       struct mcidev_sysfs_group_kobj *grp;
+       struct mem_ctl_info *mci;
+
+       debugf1("%s()\n", __func__);
+
+       grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj);
+       mci = grp->mci;
+
+       kobject_put(&mci->edac_mci_kobj);
+}
+
+/* Intermediate show/store table */
+static struct sysfs_ops inst_grp_ops = {
+       .show = inst_grp_show,
+       .store = inst_grp_store
+};
+
+/* the kobj_type instance for a instance group */
+static struct kobj_type ktype_inst_grp = {
+       .release = edac_inst_grp_release,
+       .sysfs_ops = &inst_grp_ops,
+};
+
+
 /*
  * edac_create_mci_instance_attributes
- *     create MC driver specific attributes at the topmost level
- *     directory of this mci instance.
+ *     create MC driver specific attributes bellow an specified kobj
+ * This routine calls itself recursively, in order to create an entire
+ * object tree.
  */
-static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci)
+static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
+                               struct mcidev_sysfs_attribute *sysfs_attrib,
+                               struct kobject *kobj)
 {
        int err;
-       struct mcidev_sysfs_attribute *sysfs_attrib;
 
-       /* point to the start of the array and iterate over it
-        * adding each attribute listed to this mci instance's kobject
-        */
-       sysfs_attrib = mci->mc_driver_sysfs_attributes;
+       debugf1("%s()\n", __func__);
+
+       while (sysfs_attrib) {
+               if (sysfs_attrib->grp) {
+                       struct mcidev_sysfs_group_kobj *grp_kobj;
+
+                       grp_kobj = kzalloc(sizeof(*grp_kobj), GFP_KERNEL);
+                       if (!grp_kobj)
+                               return -ENOMEM;
+
+                       list_add_tail(&grp_kobj->list, &mci->grp_kobj_list);
+
+                       grp_kobj->grp = sysfs_attrib->grp;
+                       grp_kobj->mci = mci;
+
+                       debugf0("%s() grp %s, mci %p\n", __func__,
+                               sysfs_attrib->grp->name, mci);
+
+                       err = kobject_init_and_add(&grp_kobj->kobj,
+                                               &ktype_inst_grp,
+                                               &mci->edac_mci_kobj,
+                                               sysfs_attrib->grp->name);
+                       if (err)
+                               return err;
+
+                       err = edac_create_mci_instance_attributes(mci,
+                                       grp_kobj->grp->mcidev_attr,
+                                       &grp_kobj->kobj);
+
+                       if (err)
+                               return err;
+               } else if (sysfs_attrib->attr.name) {
+                       debugf0("%s() file %s\n", __func__,
+                               sysfs_attrib->attr.name);
+
+                       err = sysfs_create_file(kobj, &sysfs_attrib->attr);
+               } else
+                       break;
 
-       while (sysfs_attrib && sysfs_attrib->attr.name) {
-               err = sysfs_create_file(&mci->edac_mci_kobj,
-                                       (struct attribute*) sysfs_attrib);
                if (err) {
                        return err;
                }
-
                sysfs_attrib++;
        }
 
@@ -759,21 +853,44 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci)
  *     remove MC driver specific attributes at the topmost level
  *     directory of this mci instance.
  */
-static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci)
+static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
+                               struct mcidev_sysfs_attribute *sysfs_attrib,
+                               struct kobject *kobj, int count)
 {
-       struct mcidev_sysfs_attribute *sysfs_attrib;
+       struct mcidev_sysfs_group_kobj *grp_kobj, *tmp;
 
-       /* point to the start of the array and iterate over it
-        * adding each attribute listed to this mci instance's kobject
-        */
-       sysfs_attrib = mci->mc_driver_sysfs_attributes;
+       debugf1("%s()\n", __func__);
 
-       /* loop if there are attributes and until we hit a NULL entry */
-       while (sysfs_attrib && sysfs_attrib->attr.name) {
-               sysfs_remove_file(&mci->edac_mci_kobj,
-                                       (struct attribute *) sysfs_attrib);
+       /*
+        * loop if there are attributes and until we hit a NULL entry
+        * Remove first all the atributes
+        */
+       while (sysfs_attrib) {
+               if (sysfs_attrib->grp) {
+                       list_for_each_entry(grp_kobj, &mci->grp_kobj_list,
+                                           list)
+                               if (grp_kobj->grp == sysfs_attrib->grp)
+                                       edac_remove_mci_instance_attributes(mci,
+                                                   grp_kobj->grp->mcidev_attr,
+                                                   &grp_kobj->kobj, count + 1);
+               } else if (sysfs_attrib->attr.name) {
+                       debugf0("%s() file %s\n", __func__,
+                               sysfs_attrib->attr.name);
+                       sysfs_remove_file(kobj, &sysfs_attrib->attr);
+               } else
+                       break;
                sysfs_attrib++;
        }
+
+       /*
+        * Now that all attributes got removed, it is save to remove all groups
+        */
+       if (!count)
+               list_for_each_entry_safe(grp_kobj, tmp, &mci->grp_kobj_list,
+                                        list) {
+                       debugf0("%s() grp %s\n", __func__, grp_kobj->grp->name);
+                       kobject_put(&grp_kobj->kobj);
+               }
 }
 
 
@@ -794,6 +911,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
 
        debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
 
+       INIT_LIST_HEAD(&mci->grp_kobj_list);
+
        /* create a symlink for the device */
        err = sysfs_create_link(kobj_mci, &mci->dev->kobj,
                                EDAC_DEVICE_SYMLINK);
@@ -806,7 +925,9 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
         * then create them now for the driver.
         */
        if (mci->mc_driver_sysfs_attributes) {
-               err = edac_create_mci_instance_attributes(mci);
+               err = edac_create_mci_instance_attributes(mci,
+                                       mci->mc_driver_sysfs_attributes,
+                                       &mci->edac_mci_kobj);
                if (err) {
                        debugf1("%s() failure to create mci attributes\n",
                                __func__);
@@ -841,7 +962,8 @@ fail1:
        }
 
        /* remove the mci instance's attributes, if any */
-       edac_remove_mci_instance_attributes(mci);
+       edac_remove_mci_instance_attributes(mci,
+               mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0);
 
        /* remove the symlink */
        sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK);
@@ -875,8 +997,9 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
        debugf0("%s()  remove_mci_instance\n", __func__);
 
        /* remove this mci instance's attribtes */
-       edac_remove_mci_instance_attributes(mci);
-
+       edac_remove_mci_instance_attributes(mci,
+                                           mci->mc_driver_sysfs_attributes,
+                                           &mci->edac_mci_kobj, 0);
        debugf0("%s()  unregister this mci kobj\n", __func__);
 
        /* unregister this instance's kobject */
diff --git a/drivers/edac/edac_mce.c b/drivers/edac/edac_mce.c
new file mode 100644 (file)
index 0000000..9ccdc5b
--- /dev/null
@@ -0,0 +1,61 @@
+/* Provides edac interface to mcelog events
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License version 2.
+ *
+ * Copyright (c) 2009 by:
+ *      Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * Red Hat Inc. http://www.redhat.com
+ */
+
+#include <linux/module.h>
+#include <linux/edac_mce.h>
+#include <asm/mce.h>
+
+int edac_mce_enabled;
+EXPORT_SYMBOL_GPL(edac_mce_enabled);
+
+
+/*
+ * Extension interface
+ */
+
+static LIST_HEAD(edac_mce_list);
+static DEFINE_MUTEX(edac_mce_lock);
+
+int edac_mce_register(struct edac_mce *edac_mce)
+{
+       mutex_lock(&edac_mce_lock);
+       list_add_tail(&edac_mce->list, &edac_mce_list);
+       mutex_unlock(&edac_mce_lock);
+       return 0;
+}
+EXPORT_SYMBOL(edac_mce_register);
+
+void edac_mce_unregister(struct edac_mce *edac_mce)
+{
+       mutex_lock(&edac_mce_lock);
+       list_del(&edac_mce->list);
+       mutex_unlock(&edac_mce_lock);
+}
+EXPORT_SYMBOL(edac_mce_unregister);
+
+int edac_mce_parse(struct mce *mce)
+{
+       struct edac_mce *edac_mce;
+
+       list_for_each_entry(edac_mce, &edac_mce_list, list) {
+               if (edac_mce->check_error(edac_mce->priv, mce))
+                       return 1;
+       }
+
+       /* Nobody queued the error */
+       return 0;
+}
+EXPORT_SYMBOL_GPL(edac_mce_parse);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("EDAC Driver for mcelog captured errors");
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
new file mode 100644 (file)
index 0000000..cc9357d
--- /dev/null
@@ -0,0 +1,2105 @@
+/* Intel i7 core/Nehalem Memory Controller kernel module
+ *
+ * This driver supports yhe memory controllers found on the Intel
+ * processor families i7core, i7core 7xx/8xx, i5core, Xeon 35xx,
+ * Xeon 55xx and Xeon 56xx also known as Nehalem, Nehalem-EP, Lynnfield
+ * and Westmere-EP.
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License version 2 only.
+ *
+ * Copyright (c) 2009-2010 by:
+ *      Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * Red Hat Inc. http://www.redhat.com
+ *
+ * Forked and adapted from the i5400_edac driver
+ *
+ * Based on the following public Intel datasheets:
+ * Intel Core i7 Processor Extreme Edition and Intel Core i7 Processor
+ * Datasheet, Volume 2:
+ *     http://download.intel.com/design/processor/datashts/320835.pdf
+ * Intel Xeon Processor 5500 Series Datasheet Volume 2
+ *     http://www.intel.com/Assets/PDF/datasheet/321322.pdf
+ * also available at:
+ *     http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/edac.h>
+#include <linux/mmzone.h>
+#include <linux/edac_mce.h>
+#include <linux/smp.h>
+#include <asm/processor.h>
+
+#include "edac_core.h"
+
+/*
+ * This is used for Nehalem-EP and Nehalem-EX devices, where the non-core
+ * registers start at bus 255, and are not reported by BIOS.
+ * We currently find devices with only 2 sockets. In order to support more QPI
+ * Quick Path Interconnect, just increment this number.
+ */
+#define MAX_SOCKET_BUSES       2
+
+
+/*
+ * Alter this version for the module when modifications are made
+ */
+#define I7CORE_REVISION    " Ver: 1.0.0 " __DATE__
+#define EDAC_MOD_STR      "i7core_edac"
+
+/*
+ * Debug macros
+ */
+#define i7core_printk(level, fmt, arg...)                      \
+       edac_printk(level, "i7core", fmt, ##arg)
+
+#define i7core_mc_printk(mci, level, fmt, arg...)              \
+       edac_mc_chipset_printk(mci, level, "i7core", fmt, ##arg)
+
+/*
+ * i7core Memory Controller Registers
+ */
+
+       /* OFFSETS for Device 0 Function 0 */
+
+#define MC_CFG_CONTROL 0x90
+
+       /* OFFSETS for Device 3 Function 0 */
+
+#define MC_CONTROL     0x48
+#define MC_STATUS      0x4c
+#define MC_MAX_DOD     0x64
+
+/*
+ * OFFSETS for Device 3 Function 4, as inicated on Xeon 5500 datasheet:
+ * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
+ */
+
+#define MC_TEST_ERR_RCV1       0x60
+  #define DIMM2_COR_ERR(r)                     ((r) & 0x7fff)
+
+#define MC_TEST_ERR_RCV0       0x64
+  #define DIMM1_COR_ERR(r)                     (((r) >> 16) & 0x7fff)
+  #define DIMM0_COR_ERR(r)                     ((r) & 0x7fff)
+
+/* OFFSETS for Device 3 Function 2, as inicated on Xeon 5500 datasheet */
+#define MC_COR_ECC_CNT_0       0x80
+#define MC_COR_ECC_CNT_1       0x84
+#define MC_COR_ECC_CNT_2       0x88
+#define MC_COR_ECC_CNT_3       0x8c
+#define MC_COR_ECC_CNT_4       0x90
+#define MC_COR_ECC_CNT_5       0x94
+
+#define DIMM_TOP_COR_ERR(r)                    (((r) >> 16) & 0x7fff)
+#define DIMM_BOT_COR_ERR(r)                    ((r) & 0x7fff)
+
+
+       /* OFFSETS for Devices 4,5 and 6 Function 0 */
+
+#define MC_CHANNEL_DIMM_INIT_PARAMS 0x58
+  #define THREE_DIMMS_PRESENT          (1 << 24)
+  #define SINGLE_QUAD_RANK_PRESENT     (1 << 23)
+  #define QUAD_RANK_PRESENT            (1 << 22)
+  #define REGISTERED_DIMM              (1 << 15)
+
+#define MC_CHANNEL_MAPPER      0x60
+  #define RDLCH(r, ch)         ((((r) >> (3 + (ch * 6))) & 0x07) - 1)
+  #define WRLCH(r, ch)         ((((r) >> (ch * 6)) & 0x07) - 1)
+
+#define MC_CHANNEL_RANK_PRESENT 0x7c
+  #define RANK_PRESENT_MASK            0xffff
+
+#define MC_CHANNEL_ADDR_MATCH  0xf0
+#define MC_CHANNEL_ERROR_MASK  0xf8
+#define MC_CHANNEL_ERROR_INJECT        0xfc
+  #define INJECT_ADDR_PARITY   0x10
+  #define INJECT_ECC           0x08
+  #define MASK_CACHELINE       0x06
+  #define MASK_FULL_CACHELINE  0x06
+  #define MASK_MSB32_CACHELINE 0x04
+  #define MASK_LSB32_CACHELINE 0x02
+  #define NO_MASK_CACHELINE    0x00
+  #define REPEAT_EN            0x01
+
+       /* OFFSETS for Devices 4,5 and 6 Function 1 */
+
+#define MC_DOD_CH_DIMM0                0x48
+#define MC_DOD_CH_DIMM1                0x4c
+#define MC_DOD_CH_DIMM2                0x50
+  #define RANKOFFSET_MASK      ((1 << 12) | (1 << 11) | (1 << 10))
+  #define RANKOFFSET(x)                ((x & RANKOFFSET_MASK) >> 10)
+  #define DIMM_PRESENT_MASK    (1 << 9)
+  #define DIMM_PRESENT(x)      (((x) & DIMM_PRESENT_MASK) >> 9)
+  #define MC_DOD_NUMBANK_MASK          ((1 << 8) | (1 << 7))
+  #define MC_DOD_NUMBANK(x)            (((x) & MC_DOD_NUMBANK_MASK) >> 7)
+  #define MC_DOD_NUMRANK_MASK          ((1 << 6) | (1 << 5))
+  #define MC_DOD_NUMRANK(x)            (((x) & MC_DOD_NUMRANK_MASK) >> 5)
+  #define MC_DOD_NUMROW_MASK           ((1 << 4) | (1 << 3) | (1 << 2))
+  #define MC_DOD_NUMROW(x)             (((x) & MC_DOD_NUMROW_MASK) >> 2)
+  #define MC_DOD_NUMCOL_MASK           3
+  #define MC_DOD_NUMCOL(x)             ((x) & MC_DOD_NUMCOL_MASK)
+
+#define MC_RANK_PRESENT                0x7c
+
+#define MC_SAG_CH_0    0x80
+#define MC_SAG_CH_1    0x84
+#define MC_SAG_CH_2    0x88
+#define MC_SAG_CH_3    0x8c
+#define MC_SAG_CH_4    0x90
+#define MC_SAG_CH_5    0x94
+#define MC_SAG_CH_6    0x98
+#define MC_SAG_CH_7    0x9c
+
+#define MC_RIR_LIMIT_CH_0      0x40
+#define MC_RIR_LIMIT_CH_1      0x44
+#define MC_RIR_LIMIT_CH_2      0x48
+#define MC_RIR_LIMIT_CH_3      0x4C
+#define MC_RIR_LIMIT_CH_4      0x50
+#define MC_RIR_LIMIT_CH_5      0x54
+#define MC_RIR_LIMIT_CH_6      0x58
+#define MC_RIR_LIMIT_CH_7      0x5C
+#define MC_RIR_LIMIT_MASK      ((1 << 10) - 1)
+
+#define MC_RIR_WAY_CH          0x80
+  #define MC_RIR_WAY_OFFSET_MASK       (((1 << 14) - 1) & ~0x7)
+  #define MC_RIR_WAY_RANK_MASK         0x7
+
+/*
+ * i7core structs
+ */
+
+#define NUM_CHANS 3
+#define MAX_DIMMS 3            /* Max DIMMS per channel */
+#define MAX_MCR_FUNC  4
+#define MAX_CHAN_FUNC 3
+
+struct i7core_info {
+       u32     mc_control;
+       u32     mc_status;
+       u32     max_dod;
+       u32     ch_map;
+};
+
+
+struct i7core_inject {
+       int     enable;
+
+       u32     section;
+       u32     type;
+       u32     eccmask;
+
+       /* Error address mask */
+       int channel, dimm, rank, bank, page, col;
+};
+
+struct i7core_channel {
+       u32             ranks;
+       u32             dimms;
+};
+
+struct pci_id_descr {
+       int                     dev;
+       int                     func;
+       int                     dev_id;
+       int                     optional;
+};
+
+struct pci_id_table {
+       struct pci_id_descr     *descr;
+       int                     n_devs;
+};
+
+struct i7core_dev {
+       struct list_head        list;
+       u8                      socket;
+       struct pci_dev          **pdev;
+       int                     n_devs;
+       struct mem_ctl_info     *mci;
+};
+
+struct i7core_pvt {
+       struct pci_dev  *pci_noncore;
+       struct pci_dev  *pci_mcr[MAX_MCR_FUNC + 1];
+       struct pci_dev  *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1];
+
+       struct i7core_dev *i7core_dev;
+
+       struct i7core_info      info;
+       struct i7core_inject    inject;
+       struct i7core_channel   channel[NUM_CHANS];
+
+       int             channels; /* Number of active channels */
+
+       int             ce_count_available;
+       int             csrow_map[NUM_CHANS][MAX_DIMMS];
+
+                       /* ECC corrected errors counts per udimm */
+       unsigned long   udimm_ce_count[MAX_DIMMS];
+       int             udimm_last_ce_count[MAX_DIMMS];
+                       /* ECC corrected errors counts per rdimm */
+       unsigned long   rdimm_ce_count[NUM_CHANS][MAX_DIMMS];
+       int             rdimm_last_ce_count[NUM_CHANS][MAX_DIMMS];
+
+       unsigned int    is_registered;
+
+       /* mcelog glue */
+       struct edac_mce         edac_mce;
+
+       /* Fifo double buffers */
+       struct mce              mce_entry[MCE_LOG_LEN];
+       struct mce              mce_outentry[MCE_LOG_LEN];
+
+       /* Fifo in/out counters */
+       unsigned                mce_in, mce_out;
+
+       /* Count indicator to show errors not got */
+       unsigned                mce_overrun;
+};
+
+/* Static vars */
+static LIST_HEAD(i7core_edac_list);
+static DEFINE_MUTEX(i7core_edac_lock);
+
+#define PCI_DESCR(device, function, device_id) \
+       .dev = (device),                        \
+       .func = (function),                     \
+       .dev_id = (device_id)
+
+struct pci_id_descr pci_dev_descr_i7core_nehalem[] = {
+               /* Memory controller */
+       { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR)     },
+       { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD)  },
+                       /* Exists only for RDIMM */
+       { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS), .optional = 1  },
+       { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
+
+               /* Channel 0 */
+       { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) },
+       { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) },
+       { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK) },
+       { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC)   },
+
+               /* Channel 1 */
+       { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL) },
+       { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR) },
+       { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK) },
+       { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC)   },
+
+               /* Channel 2 */
+       { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL) },
+       { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
+       { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
+       { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC)   },
+
+               /* Generic Non-core registers */
+       /*
+        * This is the PCI device on i7core and on Xeon 35xx (8086:2c41)
+        * On Xeon 55xx, however, it has a different id (8086:2c40). So,
+        * the probing code needs to test for the other address in case of
+        * failure of this one
+        */
+       { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE)  },
+
+};
+
+struct pci_id_descr pci_dev_descr_lynnfield[] = {
+       { PCI_DESCR( 3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR)         },
+       { PCI_DESCR( 3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD)      },
+       { PCI_DESCR( 3, 4, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST)     },
+
+       { PCI_DESCR( 4, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL) },
+       { PCI_DESCR( 4, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR) },
+       { PCI_DESCR( 4, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK) },
+       { PCI_DESCR( 4, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC)   },
+
+       { PCI_DESCR( 5, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL) },
+       { PCI_DESCR( 5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR) },
+       { PCI_DESCR( 5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK) },
+       { PCI_DESCR( 5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC)   },
+
+       /*
+        * This is the PCI device has an alternate address on some
+        * processors like Core i7 860
+        */
+       { PCI_DESCR( 0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE)     },
+};
+
+struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
+               /* Memory controller */
+       { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR_REV2)     },
+       { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD_REV2)  },
+                       /* Exists only for RDIMM */
+       { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_RAS_REV2), .optional = 1  },
+       { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST_REV2) },
+
+               /* Channel 0 */
+       { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL_REV2) },
+       { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR_REV2) },
+       { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK_REV2) },
+       { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC_REV2)   },
+
+               /* Channel 1 */
+       { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL_REV2) },
+       { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR_REV2) },
+       { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK_REV2) },
+       { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC_REV2)   },
+
+               /* Channel 2 */
+       { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_CTRL_REV2) },
+       { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2) },
+       { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2) },
+       { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2)   },
+
+               /* Generic Non-core registers */
+       { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2)  },
+
+};
+
+#define PCI_ID_TABLE_ENTRY(A) { A, ARRAY_SIZE(A) }
+struct pci_id_table pci_dev_table[] = {
+       PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_nehalem),
+       PCI_ID_TABLE_ENTRY(pci_dev_descr_lynnfield),
+       PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_westmere),
+};
+
+/*
+ *     pci_device_id   table for which devices we are looking for
+ */
+static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0)},
+       {0,}                    /* 0 terminated list. */
+};
+
+static struct edac_pci_ctl_info *i7core_pci;
+
+/****************************************************************************
+                       Anciliary status routines
+ ****************************************************************************/
+
+       /* MC_CONTROL bits */
+#define CH_ACTIVE(pvt, ch)     ((pvt)->info.mc_control & (1 << (8 + ch)))
+#define ECCx8(pvt)             ((pvt)->info.mc_control & (1 << 1))
+
+       /* MC_STATUS bits */
+#define ECC_ENABLED(pvt)       ((pvt)->info.mc_status & (1 << 4))
+#define CH_DISABLED(pvt, ch)   ((pvt)->info.mc_status & (1 << ch))
+
+       /* MC_MAX_DOD read functions */
+static inline int numdimms(u32 dimms)
+{
+       return (dimms & 0x3) + 1;
+}
+
+static inline int numrank(u32 rank)
+{
+       static int ranks[4] = { 1, 2, 4, -EINVAL };
+
+       return ranks[rank & 0x3];
+}
+
+static inline int numbank(u32 bank)
+{
+       static int banks[4] = { 4, 8, 16, -EINVAL };
+
+       return banks[bank & 0x3];
+}
+
+static inline int numrow(u32 row)
+{
+       static int rows[8] = {
+               1 << 12, 1 << 13, 1 << 14, 1 << 15,
+               1 << 16, -EINVAL, -EINVAL, -EINVAL,
+       };
+
+       return rows[row & 0x7];
+}
+
+static inline int numcol(u32 col)
+{
+       static int cols[8] = {
+               1 << 10, 1 << 11, 1 << 12, -EINVAL,
+       };
+       return cols[col & 0x3];
+}
+
+static struct i7core_dev *get_i7core_dev(u8 socket)
+{
+       struct i7core_dev *i7core_dev;
+
+       list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
+               if (i7core_dev->socket == socket)
+                       return i7core_dev;
+       }
+
+       return NULL;
+}
+
+/****************************************************************************
+                       Memory check routines
+ ****************************************************************************/
+static struct pci_dev *get_pdev_slot_func(u8 socket, unsigned slot,
+                                         unsigned func)
+{
+       struct i7core_dev *i7core_dev = get_i7core_dev(socket);
+       int i;
+
+       if (!i7core_dev)
+               return NULL;
+
+       for (i = 0; i < i7core_dev->n_devs; i++) {
+               if (!i7core_dev->pdev[i])
+                       continue;
+
+               if (PCI_SLOT(i7core_dev->pdev[i]->devfn) == slot &&
+                   PCI_FUNC(i7core_dev->pdev[i]->devfn) == func) {
+                       return i7core_dev->pdev[i];
+               }
+       }
+
+       return NULL;
+}
+
+/**
+ * i7core_get_active_channels() - gets the number of channels and csrows
+ * @socket:    Quick Path Interconnect socket
+ * @channels:  Number of channels that will be returned
+ * @csrows:    Number of csrows found
+ *
+ * Since EDAC core needs to know in advance the number of available channels
+ * and csrows, in order to allocate memory for csrows/channels, it is needed
+ * to run two similar steps. At the first step, implemented on this function,
+ * it checks the number of csrows/channels present at one socket.
+ * this is used in order to properly allocate the size of mci components.
+ *
+ * It should be noticed that none of the current available datasheets explain
+ * or even mention how csrows are seen by the memory controller. So, we need
+ * to add a fake description for csrows.
+ * So, this driver is attributing one DIMM memory for one csrow.
+ */
+static int i7core_get_active_channels(u8 socket, unsigned *channels,
+                                     unsigned *csrows)
+{
+       struct pci_dev *pdev = NULL;
+       int i, j;
+       u32 status, control;
+
+       *channels = 0;
+       *csrows = 0;
+
+       pdev = get_pdev_slot_func(socket, 3, 0);
+       if (!pdev) {
+               i7core_printk(KERN_ERR, "Couldn't find socket %d fn 3.0!!!\n",
+                             socket);
+               return -ENODEV;
+       }
+
+       /* Device 3 function 0 reads */
+       pci_read_config_dword(pdev, MC_STATUS, &status);
+       pci_read_config_dword(pdev, MC_CONTROL, &control);
+
+       for (i = 0; i < NUM_CHANS; i++) {
+               u32 dimm_dod[3];
+               /* Check if the channel is active */
+               if (!(control & (1 << (8 + i))))
+                       continue;
+
+               /* Check if the channel is disabled */
+               if (status & (1 << i))
+                       continue;
+
+               pdev = get_pdev_slot_func(socket, i + 4, 1);
+               if (!pdev) {
+                       i7core_printk(KERN_ERR, "Couldn't find socket %d "
+                                               "fn %d.%d!!!\n",
+                                               socket, i + 4, 1);
+                       return -ENODEV;
+               }
+               /* Devices 4-6 function 1 */
+               pci_read_config_dword(pdev,
+                               MC_DOD_CH_DIMM0, &dimm_dod[0]);
+               pci_read_config_dword(pdev,
+                               MC_DOD_CH_DIMM1, &dimm_dod[1]);
+               pci_read_config_dword(pdev,
+                               MC_DOD_CH_DIMM2, &dimm_dod[2]);
+
+               (*channels)++;
+
+               for (j = 0; j < 3; j++) {
+                       if (!DIMM_PRESENT(dimm_dod[j]))
+                               continue;
+                       (*csrows)++;
+               }
+       }
+
+       debugf0("Number of active channels on socket %d: %d\n",
+               socket, *channels);
+
+       return 0;
+}
+
+static int get_dimm_config(struct mem_ctl_info *mci, int *csrow)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       struct csrow_info *csr;
+       struct pci_dev *pdev;
+       int i, j;
+       unsigned long last_page = 0;
+       enum edac_type mode;
+       enum mem_type mtype;
+
+       /* Get data from the MC register, function 0 */
+       pdev = pvt->pci_mcr[0];
+       if (!pdev)
+               return -ENODEV;
+
+       /* Device 3 function 0 reads */
+       pci_read_config_dword(pdev, MC_CONTROL, &pvt->info.mc_control);
+       pci_read_config_dword(pdev, MC_STATUS, &pvt->info.mc_status);
+       pci_read_config_dword(pdev, MC_MAX_DOD, &pvt->info.max_dod);
+       pci_read_config_dword(pdev, MC_CHANNEL_MAPPER, &pvt->info.ch_map);
+
+       debugf0("QPI %d control=0x%08x status=0x%08x dod=0x%08x map=0x%08x\n",
+               pvt->i7core_dev->socket, pvt->info.mc_control, pvt->info.mc_status,
+               pvt->info.max_dod, pvt->info.ch_map);
+
+       if (ECC_ENABLED(pvt)) {
+               debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt) ? 8 : 4);
+               if (ECCx8(pvt))
+                       mode = EDAC_S8ECD8ED;
+               else
+                       mode = EDAC_S4ECD4ED;
+       } else {
+               debugf0("ECC disabled\n");
+               mode = EDAC_NONE;
+       }
+
+       /* FIXME: need to handle the error codes */
+       debugf0("DOD Max limits: DIMMS: %d, %d-ranked, %d-banked "
+               "x%x x 0x%x\n",
+               numdimms(pvt->info.max_dod),
+               numrank(pvt->info.max_dod >> 2),
+               numbank(pvt->info.max_dod >> 4),
+               numrow(pvt->info.max_dod >> 6),
+               numcol(pvt->info.max_dod >> 9));
+
+       for (i = 0; i < NUM_CHANS; i++) {
+               u32 data, dimm_dod[3], value[8];
+
+               if (!pvt->pci_ch[i][0])
+                       continue;
+
+               if (!CH_ACTIVE(pvt, i)) {
+                       debugf0("Channel %i is not active\n", i);
+                       continue;
+               }
+               if (CH_DISABLED(pvt, i)) {
+                       debugf0("Channel %i is disabled\n", i);
+                       continue;
+               }
+
+               /* Devices 4-6 function 0 */
+               pci_read_config_dword(pvt->pci_ch[i][0],
+                               MC_CHANNEL_DIMM_INIT_PARAMS, &data);
+
+               pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT) ?
+                                               4 : 2;
+
+               if (data & REGISTERED_DIMM)
+                       mtype = MEM_RDDR3;
+               else
+                       mtype = MEM_DDR3;
+#if 0
+               if (data & THREE_DIMMS_PRESENT)
+                       pvt->channel[i].dimms = 3;
+               else if (data & SINGLE_QUAD_RANK_PRESENT)
+                       pvt->channel[i].dimms = 1;
+               else
+                       pvt->channel[i].dimms = 2;
+#endif
+
+               /* Devices 4-6 function 1 */
+               pci_read_config_dword(pvt->pci_ch[i][1],
+                               MC_DOD_CH_DIMM0, &dimm_dod[0]);
+               pci_read_config_dword(pvt->pci_ch[i][1],
+                               MC_DOD_CH_DIMM1, &dimm_dod[1]);
+               pci_read_config_dword(pvt->pci_ch[i][1],
+                               MC_DOD_CH_DIMM2, &dimm_dod[2]);
+
+               debugf0("Ch%d phy rd%d, wr%d (0x%08x): "
+                       "%d ranks, %cDIMMs\n",
+                       i,
+                       RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i),
+                       data,
+                       pvt->channel[i].ranks,
+                       (data & REGISTERED_DIMM) ? 'R' : 'U');
+
+               for (j = 0; j < 3; j++) {
+                       u32 banks, ranks, rows, cols;
+                       u32 size, npages;
+
+                       if (!DIMM_PRESENT(dimm_dod[j]))
+                               continue;
+
+                       banks = numbank(MC_DOD_NUMBANK(dimm_dod[j]));
+                       ranks = numrank(MC_DOD_NUMRANK(dimm_dod[j]));
+                       rows = numrow(MC_DOD_NUMROW(dimm_dod[j]));
+                       cols = numcol(MC_DOD_NUMCOL(dimm_dod[j]));
+
+                       /* DDR3 has 8 I/O banks */
+                       size = (rows * cols * banks * ranks) >> (20 - 3);
+
+                       pvt->channel[i].dimms++;
+
+                       debugf0("\tdimm %d %d Mb offset: %x, "
+                               "bank: %d, rank: %d, row: %#x, col: %#x\n",
+                               j, size,
+                               RANKOFFSET(dimm_dod[j]),
+                               banks, ranks, rows, cols);
+
+#if PAGE_SHIFT > 20
+                       npages = size >> (PAGE_SHIFT - 20);
+#else
+                       npages = size << (20 - PAGE_SHIFT);
+#endif
+
+                       csr = &mci->csrows[*csrow];
+                       csr->first_page = last_page + 1;
+                       last_page += npages;
+                       csr->last_page = last_page;
+                       csr->nr_pages = npages;
+
+                       csr->page_mask = 0;
+                       csr->grain = 8;
+                       csr->csrow_idx = *csrow;
+                       csr->nr_channels = 1;
+
+                       csr->channels[0].chan_idx = i;
+                       csr->channels[0].ce_count = 0;
+
+                       pvt->csrow_map[i][j] = *csrow;
+
+                       switch (banks) {
+                       case 4:
+                               csr->dtype = DEV_X4;
+                               break;
+                       case 8:
+                               csr->dtype = DEV_X8;
+                               break;
+                       case 16:
+                               csr->dtype = DEV_X16;
+                               break;
+                       default:
+                               csr->dtype = DEV_UNKNOWN;
+                       }
+
+                       csr->edac_mode = mode;
+                       csr->mtype = mtype;
+
+                       (*csrow)++;
+               }
+
+               pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
+               pci_read_config_dword(pdev, MC_SAG_CH_1, &value[1]);
+               pci_read_config_dword(pdev, MC_SAG_CH_2, &value[2]);
+               pci_read_config_dword(pdev, MC_SAG_CH_3, &value[3]);
+               pci_read_config_dword(pdev, MC_SAG_CH_4, &value[4]);
+               pci_read_config_dword(pdev, MC_SAG_CH_5, &value[5]);
+               pci_read_config_dword(pdev, MC_SAG_CH_6, &value[6]);
+               pci_read_config_dword(pdev, MC_SAG_CH_7, &value[7]);
+               debugf1("\t[%i] DIVBY3\tREMOVED\tOFFSET\n", i);
+               for (j = 0; j < 8; j++)
+                       debugf1("\t\t%#x\t%#x\t%#x\n",
+                               (value[j] >> 27) & 0x1,
+                               (value[j] >> 24) & 0x7,
+                               (value[j] && ((1 << 24) - 1)));
+       }
+
+       return 0;
+}
+
+/****************************************************************************
+                       Error insertion routines
+ ****************************************************************************/
+
+/* The i7core has independent error injection features per channel.
+   However, to have a simpler code, we don't allow enabling error injection
+   on more than one channel.
+   Also, since a change at an inject parameter will be applied only at enable,
+   we're disabling error injection on all write calls to the sysfs nodes that
+   controls the error code injection.
+ */
+static int disable_inject(struct mem_ctl_info *mci)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+
+       pvt->inject.enable = 0;
+
+       if (!pvt->pci_ch[pvt->inject.channel][0])
+               return -ENODEV;
+
+       pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
+                               MC_CHANNEL_ERROR_INJECT, 0);
+
+       return 0;
+}
+
+/*
+ * i7core inject inject.section
+ *
+ *     accept and store error injection inject.section value
+ *     bit 0 - refers to the lower 32-byte half cacheline
+ *     bit 1 - refers to the upper 32-byte half cacheline
+ */
+static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci,
+                                          const char *data, size_t count)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       unsigned long value;
+       int rc;
+
+       if (pvt->inject.enable)
+               disable_inject(mci);
+
+       rc = strict_strtoul(data, 10, &value);
+       if ((rc < 0) || (value > 3))
+               return -EIO;
+
+       pvt->inject.section = (u32) value;
+       return count;
+}
+
+static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci,
+                                             char *data)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       return sprintf(data, "0x%08x\n", pvt->inject.section);
+}
+
+/*
+ * i7core inject.type
+ *
+ *     accept and store error injection inject.section value
+ *     bit 0 - repeat enable - Enable error repetition
+ *     bit 1 - inject ECC error
+ *     bit 2 - inject parity error
+ */
+static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci,
+                                       const char *data, size_t count)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       unsigned long value;
+       int rc;
+
+       if (pvt->inject.enable)
+               disable_inject(mci);
+
+       rc = strict_strtoul(data, 10, &value);
+       if ((rc < 0) || (value > 7))
+               return -EIO;
+
+       pvt->inject.type = (u32) value;
+       return count;
+}
+
+static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci,
+                                             char *data)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       return sprintf(data, "0x%08x\n", pvt->inject.type);
+}
+
+/*
+ * i7core_inject_inject.eccmask_store
+ *
+ * The type of error (UE/CE) will depend on the inject.eccmask value:
+ *   Any bits set to a 1 will flip the corresponding ECC bit
+ *   Correctable errors can be injected by flipping 1 bit or the bits within
+ *   a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
+ *   23:16 and 31:24). Flipping bits in two symbol pairs will cause an
+ *   uncorrectable error to be injected.
+ */
+static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci,
+                                       const char *data, size_t count)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       unsigned long value;
+       int rc;
+
+       if (pvt->inject.enable)
+               disable_inject(mci);
+
+       rc = strict_strtoul(data, 10, &value);
+       if (rc < 0)
+               return -EIO;
+
+       pvt->inject.eccmask = (u32) value;
+       return count;
+}
+
+static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci,
+                                             char *data)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       return sprintf(data, "0x%08x\n", pvt->inject.eccmask);
+}
+
+/*
+ * i7core_addrmatch
+ *
+ * The type of error (UE/CE) will depend on the inject.eccmask value:
+ *   Any bits set to a 1 will flip the corresponding ECC bit
+ *   Correctable errors can be injected by flipping 1 bit or the bits within
+ *   a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
+ *   23:16 and 31:24). Flipping bits in two symbol pairs will cause an
+ *   uncorrectable error to be injected.
+ */
+
+#define DECLARE_ADDR_MATCH(param, limit)                       \
+static ssize_t i7core_inject_store_##param(                    \
+               struct mem_ctl_info *mci,                       \
+               const char *data, size_t count)                 \
+{                                                              \
+       struct i7core_pvt *pvt;                                 \
+       long value;                                             \
+       int rc;                                                 \
+                                                               \
+       debugf1("%s()\n", __func__);                            \
+       pvt = mci->pvt_info;                                    \
+                                                               \
+       if (pvt->inject.enable)                                 \
+               disable_inject(mci);                            \
+                                                               \
+       if (!strcasecmp(data, "any") || !strcasecmp(data, "any\n"))\
+               value = -1;                                     \
+       else {                                                  \
+               rc = strict_strtoul(data, 10, &value);          \
+               if ((rc < 0) || (value >= limit))               \
+                       return -EIO;                            \
+       }                                                       \
+                                                               \
+       pvt->inject.param = value;                              \
+                                                               \
+       return count;                                           \
+}                                                              \
+                                                               \
+static ssize_t i7core_inject_show_##param(                     \
+               struct mem_ctl_info *mci,                       \
+               char *data)                                     \
+{                                                              \
+       struct i7core_pvt *pvt;                                 \
+                                                               \
+       pvt = mci->pvt_info;                                    \
+       debugf1("%s() pvt=%p\n", __func__, pvt);                \
+       if (pvt->inject.param < 0)                              \
+               return sprintf(data, "any\n");                  \
+       else                                                    \
+               return sprintf(data, "%d\n", pvt->inject.param);\
+}
+
+#define ATTR_ADDR_MATCH(param)                                 \
+       {                                                       \
+               .attr = {                                       \
+                       .name = #param,                         \
+                       .mode = (S_IRUGO | S_IWUSR)             \
+               },                                              \
+               .show  = i7core_inject_show_##param,            \
+               .store = i7core_inject_store_##param,           \
+       }
+
+DECLARE_ADDR_MATCH(channel, 3);
+DECLARE_ADDR_MATCH(dimm, 3);
+DECLARE_ADDR_MATCH(rank, 4);
+DECLARE_ADDR_MATCH(bank, 32);
+DECLARE_ADDR_MATCH(page, 0x10000);
+DECLARE_ADDR_MATCH(col, 0x4000);
+
+static int write_and_test(struct pci_dev *dev, int where, u32 val)
+{
+       u32 read;
+       int count;
+
+       debugf0("setting pci %02x:%02x.%x reg=%02x value=%08x\n",
+               dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
+               where, val);
+
+       for (count = 0; count < 10; count++) {
+               if (count)
+                       msleep(100);
+               pci_write_config_dword(dev, where, val);
+               pci_read_config_dword(dev, where, &read);
+
+               if (read == val)
+                       return 0;
+       }
+
+       i7core_printk(KERN_ERR, "Error during set pci %02x:%02x.%x reg=%02x "
+               "write=%08x. Read=%08x\n",
+               dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
+               where, val, read);
+
+       return -EINVAL;
+}
+
+/*
+ * This routine prepares the Memory Controller for error injection.
+ * The error will be injected when some process tries to write to the
+ * memory that matches the given criteria.
+ * The criteria can be set in terms of a mask where dimm, rank, bank, page
+ * and col can be specified.
+ * A -1 value for any of the mask items will make the MCU to ignore
+ * that matching criteria for error injection.
+ *
+ * It should be noticed that the error will only happen after a write operation
+ * on a memory that matches the condition. if REPEAT_EN is not enabled at
+ * inject mask, then it will produce just one error. Otherwise, it will repeat
+ * until the injectmask would be cleaned.
+ *
+ * FIXME: This routine assumes that MAXNUMDIMMS value of MC_MAX_DOD
+ *    is reliable enough to check if the MC is using the
+ *    three channels. However, this is not clear at the datasheet.
+ */
+static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
+                                      const char *data, size_t count)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       u32 injectmask;
+       u64 mask = 0;
+       int  rc;
+       long enable;
+
+       if (!pvt->pci_ch[pvt->inject.channel][0])
+               return 0;
+
+       rc = strict_strtoul(data, 10, &enable);
+       if ((rc < 0))
+               return 0;
+
+       if (enable) {
+               pvt->inject.enable = 1;
+       } else {
+               disable_inject(mci);
+               return count;
+       }
+
+       /* Sets pvt->inject.dimm mask */
+       if (pvt->inject.dimm < 0)
+               mask |= 1LL << 41;
+       else {
+               if (pvt->channel[pvt->inject.channel].dimms > 2)
+                       mask |= (pvt->inject.dimm & 0x3LL) << 35;
+               else
+                       mask |= (pvt->inject.dimm & 0x1LL) << 36;
+       }
+
+       /* Sets pvt->inject.rank mask */
+       if (pvt->inject.rank < 0)
+               mask |= 1LL << 40;
+       else {
+               if (pvt->channel[pvt->inject.channel].dimms > 2)
+                       mask |= (pvt->inject.rank & 0x1LL) << 34;
+               else
+                       mask |= (pvt->inject.rank & 0x3LL) << 34;
+       }
+
+       /* Sets pvt->inject.bank mask */
+       if (pvt->inject.bank < 0)
+               mask |= 1LL << 39;
+       else
+               mask |= (pvt->inject.bank & 0x15LL) << 30;
+
+       /* Sets pvt->inject.page mask */
+       if (pvt->inject.page < 0)
+               mask |= 1LL << 38;
+       else
+               mask |= (pvt->inject.page & 0xffff) << 14;
+
+       /* Sets pvt->inject.column mask */
+       if (pvt->inject.col < 0)
+               mask |= 1LL << 37;
+       else
+               mask |= (pvt->inject.col & 0x3fff);
+
+       /*
+        * bit    0: REPEAT_EN
+        * bits 1-2: MASK_HALF_CACHELINE
+        * bit    3: INJECT_ECC
+        * bit    4: INJECT_ADDR_PARITY
+        */
+
+       injectmask = (pvt->inject.type & 1) |
+                    (pvt->inject.section & 0x3) << 1 |
+                    (pvt->inject.type & 0x6) << (3 - 1);
+
+       /* Unlock writes to registers - this register is write only */
+       pci_write_config_dword(pvt->pci_noncore,
+                              MC_CFG_CONTROL, 0x2);
+
+       write_and_test(pvt->pci_ch[pvt->inject.channel][0],
+                              MC_CHANNEL_ADDR_MATCH, mask);
+       write_and_test(pvt->pci_ch[pvt->inject.channel][0],
+                              MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L);
+
+       write_and_test(pvt->pci_ch[pvt->inject.channel][0],
+                              MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask);
+
+       write_and_test(pvt->pci_ch[pvt->inject.channel][0],
+                              MC_CHANNEL_ERROR_INJECT, injectmask);
+
+       /*
+        * This is something undocumented, based on my tests
+        * Without writing 8 to this register, errors aren't injected. Not sure
+        * why.
+        */
+       pci_write_config_dword(pvt->pci_noncore,
+                              MC_CFG_CONTROL, 8);
+
+       debugf0("Error inject addr match 0x%016llx, ecc 0x%08x,"
+               " inject 0x%08x\n",
+               mask, pvt->inject.eccmask, injectmask);
+
+
+       return count;
+}
+
+static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
+                                       char *data)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       u32 injectmask;
+
+       if (!pvt->pci_ch[pvt->inject.channel][0])
+               return 0;
+
+       pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
+                              MC_CHANNEL_ERROR_INJECT, &injectmask);
+
+       debugf0("Inject error read: 0x%018x\n", injectmask);
+
+       if (injectmask & 0x0c)
+               pvt->inject.enable = 1;
+
+       return sprintf(data, "%d\n", pvt->inject.enable);
+}
+
+#define DECLARE_COUNTER(param)                                 \
+static ssize_t i7core_show_counter_##param(                    \
+               struct mem_ctl_info *mci,                       \
+               char *data)                                     \
+{                                                              \
+       struct i7core_pvt *pvt = mci->pvt_info;                 \
+                                                               \
+       debugf1("%s() \n", __func__);                           \
+       if (!pvt->ce_count_available || (pvt->is_registered))   \
+               return sprintf(data, "data unavailable\n");     \
+       return sprintf(data, "%lu\n",                           \
+                       pvt->udimm_ce_count[param]);            \
+}
+
+#define ATTR_COUNTER(param)                                    \
+       {                                                       \
+               .attr = {                                       \
+                       .name = __stringify(udimm##param),      \
+                       .mode = (S_IRUGO | S_IWUSR)             \
+               },                                              \
+               .show  = i7core_show_counter_##param            \
+       }
+
+DECLARE_COUNTER(0);
+DECLARE_COUNTER(1);
+DECLARE_COUNTER(2);
+
+/*
+ * Sysfs struct
+ */
+
+
+static struct mcidev_sysfs_attribute i7core_addrmatch_attrs[] = {
+       ATTR_ADDR_MATCH(channel),
+       ATTR_ADDR_MATCH(dimm),
+       ATTR_ADDR_MATCH(rank),
+       ATTR_ADDR_MATCH(bank),
+       ATTR_ADDR_MATCH(page),
+       ATTR_ADDR_MATCH(col),
+       { .attr = { .name = NULL } }
+};
+
+static struct mcidev_sysfs_group i7core_inject_addrmatch = {
+       .name  = "inject_addrmatch",
+       .mcidev_attr = i7core_addrmatch_attrs,
+};
+
+static struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = {
+       ATTR_COUNTER(0),
+       ATTR_COUNTER(1),
+       ATTR_COUNTER(2),
+};
+
+static struct mcidev_sysfs_group i7core_udimm_counters = {
+       .name  = "all_channel_counts",
+       .mcidev_attr = i7core_udimm_counters_attrs,
+};
+
+static struct mcidev_sysfs_attribute i7core_sysfs_attrs[] = {
+       {
+               .attr = {
+                       .name = "inject_section",
+                       .mode = (S_IRUGO | S_IWUSR)
+               },
+               .show  = i7core_inject_section_show,
+               .store = i7core_inject_section_store,
+       }, {
+               .attr = {
+                       .name = "inject_type",
+                       .mode = (S_IRUGO | S_IWUSR)
+               },
+               .show  = i7core_inject_type_show,
+               .store = i7core_inject_type_store,
+       }, {
+               .attr = {
+                       .name = "inject_eccmask",
+                       .mode = (S_IRUGO | S_IWUSR)
+               },
+               .show  = i7core_inject_eccmask_show,
+               .store = i7core_inject_eccmask_store,
+       }, {
+               .grp = &i7core_inject_addrmatch,
+       }, {
+               .attr = {
+                       .name = "inject_enable",
+                       .mode = (S_IRUGO | S_IWUSR)
+               },
+               .show  = i7core_inject_enable_show,
+               .store = i7core_inject_enable_store,
+       },
+       { .attr = { .name = NULL } },   /* Reserved for udimm counters */
+       { .attr = { .name = NULL } }
+};
+
+/****************************************************************************
+       Device initialization routines: put/get, init/exit
+ ****************************************************************************/
+
+/*
+ *     i7core_put_devices      'put' all the devices that we have
+ *                             reserved via 'get'
+ */
+static void i7core_put_devices(struct i7core_dev *i7core_dev)
+{
+       int i;
+
+       debugf0(__FILE__ ": %s()\n", __func__);
+       for (i = 0; i < i7core_dev->n_devs; i++) {
+               struct pci_dev *pdev = i7core_dev->pdev[i];
+               if (!pdev)
+                       continue;
+               debugf0("Removing dev %02x:%02x.%d\n",
+                       pdev->bus->number,
+                       PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+               pci_dev_put(pdev);
+       }
+       kfree(i7core_dev->pdev);
+       list_del(&i7core_dev->list);
+       kfree(i7core_dev);
+}
+
+static void i7core_put_all_devices(void)
+{
+       struct i7core_dev *i7core_dev, *tmp;
+
+       list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list)
+               i7core_put_devices(i7core_dev);
+}
+
+static void __init i7core_xeon_pci_fixup(struct pci_id_table *table)
+{
+       struct pci_dev *pdev = NULL;
+       int i;
+       /*
+        * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core pci buses
+        * aren't announced by acpi. So, we need to use a legacy scan probing
+        * to detect them
+        */
+       while (table && table->descr) {
+               pdev = pci_get_device(PCI_VENDOR_ID_INTEL, table->descr[0].dev_id, NULL);
+               if (unlikely(!pdev)) {
+                       for (i = 0; i < MAX_SOCKET_BUSES; i++)
+                               pcibios_scan_specific_bus(255-i);
+               }
+               pci_dev_put(pdev);
+               table++;
+       }
+}
+
+static unsigned i7core_pci_lastbus(void)
+{
+       int last_bus = 0, bus;
+       struct pci_bus *b = NULL;
+
+       while ((b = pci_find_next_bus(b)) != NULL) {
+               bus = b->number;
+               debugf0("Found bus %d\n", bus);
+               if (bus > last_bus)
+                       last_bus = bus;
+       }
+
+       debugf0("Last bus %d\n", last_bus);
+
+       return last_bus;
+}
+
+/*
+ *     i7core_get_devices      Find and perform 'get' operation on the MCH's
+ *                     device/functions we want to reference for this driver
+ *
+ *                     Need to 'get' device 16 func 1 and func 2
+ */
+int i7core_get_onedevice(struct pci_dev **prev, int devno,
+                        struct pci_id_descr *dev_descr, unsigned n_devs,
+                        unsigned last_bus)
+{
+       struct i7core_dev *i7core_dev;
+
+       struct pci_dev *pdev = NULL;
+       u8 bus = 0;
+       u8 socket = 0;
+
+       pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                             dev_descr->dev_id, *prev);
+
+       /*
+        * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
+        * is at addr 8086:2c40, instead of 8086:2c41. So, we need
+        * to probe for the alternate address in case of failure
+        */
+       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
+               pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                     PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
+
+       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
+               pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                     PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
+                                     *prev);
+
+       if (!pdev) {
+               if (*prev) {
+                       *prev = pdev;
+                       return 0;
+               }
+
+               if (dev_descr->optional)
+                       return 0;
+
+               if (devno == 0)
+                       return -ENODEV;
+
+               i7core_printk(KERN_ERR,
+                       "Device not found: dev %02x.%d PCI ID %04x:%04x\n",
+                       dev_descr->dev, dev_descr->func,
+                       PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+               /* End of list, leave */
+               return -ENODEV;
+       }
+       bus = pdev->bus->number;
+
+       socket = last_bus - bus;
+
+       i7core_dev = get_i7core_dev(socket);
+       if (!i7core_dev) {
+               i7core_dev = kzalloc(sizeof(*i7core_dev), GFP_KERNEL);
+               if (!i7core_dev)
+                       return -ENOMEM;
+               i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * n_devs,
+                                          GFP_KERNEL);
+               if (!i7core_dev->pdev) {
+                       kfree(i7core_dev);
+                       return -ENOMEM;
+               }
+               i7core_dev->socket = socket;
+               i7core_dev->n_devs = n_devs;
+               list_add_tail(&i7core_dev->list, &i7core_edac_list);
+       }
+
+       if (i7core_dev->pdev[devno]) {
+               i7core_printk(KERN_ERR,
+                       "Duplicated device for "
+                       "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+                       bus, dev_descr->dev, dev_descr->func,
+                       PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+               pci_dev_put(pdev);
+               return -ENODEV;
+       }
+
+       i7core_dev->pdev[devno] = pdev;
+
+       /* Sanity check */
+       if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
+                       PCI_FUNC(pdev->devfn) != dev_descr->func)) {
+               i7core_printk(KERN_ERR,
+                       "Device PCI ID %04x:%04x "
+                       "has dev %02x:%02x.%d instead of dev %02x:%02x.%d\n",
+                       PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
+                       bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+                       bus, dev_descr->dev, dev_descr->func);
+               return -ENODEV;
+       }
+
+       /* Be sure that the device is enabled */
+       if (unlikely(pci_enable_device(pdev) < 0)) {
+               i7core_printk(KERN_ERR,
+                       "Couldn't enable "
+                       "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+                       bus, dev_descr->dev, dev_descr->func,
+                       PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+               return -ENODEV;
+       }
+
+       debugf0("Detected socket %d dev %02x:%02x.%d PCI ID %04x:%04x\n",
+               socket, bus, dev_descr->dev,
+               dev_descr->func,
+               PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+       *prev = pdev;
+
+       return 0;
+}
+
+static int i7core_get_devices(struct pci_id_table *table)
+{
+       int i, rc, last_bus;
+       struct pci_dev *pdev = NULL;
+       struct pci_id_descr *dev_descr;
+
+       last_bus = i7core_pci_lastbus();
+
+       while (table && table->descr) {
+               dev_descr = table->descr;
+               for (i = 0; i < table->n_devs; i++) {
+                       pdev = NULL;
+                       do {
+                               rc = i7core_get_onedevice(&pdev, i,
+                                                         &dev_descr[i],
+                                                         table->n_devs,
+                                                         last_bus);
+                               if (rc < 0) {
+                                       if (i == 0) {
+                                               i = table->n_devs;
+                                               break;
+                                       }
+                                       i7core_put_all_devices();
+                                       return -ENODEV;
+                               }
+                       } while (pdev);
+               }
+               table++;
+       }
+
+       return 0;
+       return 0;
+}
+
+static int mci_bind_devs(struct mem_ctl_info *mci,
+                        struct i7core_dev *i7core_dev)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       struct pci_dev *pdev;
+       int i, func, slot;
+
+       /* Associates i7core_dev and mci for future usage */
+       pvt->i7core_dev = i7core_dev;
+       i7core_dev->mci = mci;
+
+       pvt->is_registered = 0;
+       for (i = 0; i < i7core_dev->n_devs; i++) {
+               pdev = i7core_dev->pdev[i];
+               if (!pdev)
+                       continue;
+
+               func = PCI_FUNC(pdev->devfn);
+               slot = PCI_SLOT(pdev->devfn);
+               if (slot == 3) {
+                       if (unlikely(func > MAX_MCR_FUNC))
+                               goto error;
+                       pvt->pci_mcr[func] = pdev;
+               } else if (likely(slot >= 4 && slot < 4 + NUM_CHANS)) {
+                       if (unlikely(func > MAX_CHAN_FUNC))
+                               goto error;
+                       pvt->pci_ch[slot - 4][func] = pdev;
+               } else if (!slot && !func)
+                       pvt->pci_noncore = pdev;
+               else
+                       goto error;
+
+               debugf0("Associated fn %d.%d, dev = %p, socket %d\n",
+                       PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+                       pdev, i7core_dev->socket);
+
+               if (PCI_SLOT(pdev->devfn) == 3 &&
+                       PCI_FUNC(pdev->devfn) == 2)
+                       pvt->is_registered = 1;
+       }
+
+       /*
+        * Add extra nodes to count errors on udimm
+        * For registered memory, this is not needed, since the counters
+        * are already displayed at the standard locations
+        */
+       if (!pvt->is_registered)
+               i7core_sysfs_attrs[ARRAY_SIZE(i7core_sysfs_attrs)-2].grp =
+                       &i7core_udimm_counters;
+
+       return 0;
+
+error:
+       i7core_printk(KERN_ERR, "Device %d, function %d "
+                     "is out of the expected range\n",
+                     slot, func);
+       return -EINVAL;
+}
+
+/****************************************************************************
+                       Error check routines
+ ****************************************************************************/
+static void i7core_rdimm_update_csrow(struct mem_ctl_info *mci,
+                                        int chan, int dimm, int add)
+{
+       char *msg;
+       struct i7core_pvt *pvt = mci->pvt_info;
+       int row = pvt->csrow_map[chan][dimm], i;
+
+       for (i = 0; i < add; i++) {
+               msg = kasprintf(GFP_KERNEL, "Corrected error "
+                               "(Socket=%d channel=%d dimm=%d)",
+                               pvt->i7core_dev->socket, chan, dimm);
+
+               edac_mc_handle_fbd_ce(mci, row, 0, msg);
+               kfree (msg);
+       }
+}
+
+static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci,
+                       int chan, int new0, int new1, int new2)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       int add0 = 0, add1 = 0, add2 = 0;
+       /* Updates CE counters if it is not the first time here */
+       if (pvt->ce_count_available) {
+               /* Updates CE counters */
+
+               add2 = new2 - pvt->rdimm_last_ce_count[chan][2];
+               add1 = new1 - pvt->rdimm_last_ce_count[chan][1];
+               add0 = new0 - pvt->rdimm_last_ce_count[chan][0];
+
+               if (add2 < 0)
+                       add2 += 0x7fff;
+               pvt->rdimm_ce_count[chan][2] += add2;
+
+               if (add1 < 0)
+                       add1 += 0x7fff;
+               pvt->rdimm_ce_count[chan][1] += add1;
+
+               if (add0 < 0)
+                       add0 += 0x7fff;
+               pvt->rdimm_ce_count[chan][0] += add0;
+       } else
+               pvt->ce_count_available = 1;
+
+       /* Store the new values */
+       pvt->rdimm_last_ce_count[chan][2] = new2;
+       pvt->rdimm_last_ce_count[chan][1] = new1;
+       pvt->rdimm_last_ce_count[chan][0] = new0;
+
+       /*updated the edac core */
+       if (add0 != 0)
+               i7core_rdimm_update_csrow(mci, chan, 0, add0);
+       if (add1 != 0)
+               i7core_rdimm_update_csrow(mci, chan, 1, add1);
+       if (add2 != 0)
+               i7core_rdimm_update_csrow(mci, chan, 2, add2);
+
+}
+
+static void i7core_rdimm_check_mc_ecc_err(struct mem_ctl_info *mci)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       u32 rcv[3][2];
+       int i, new0, new1, new2;
+
+       /*Read DEV 3: FUN 2:  MC_COR_ECC_CNT regs directly*/
+       pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_0,
+                                                               &rcv[0][0]);
+       pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_1,
+                                                               &rcv[0][1]);
+       pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_2,
+                                                               &rcv[1][0]);
+       pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_3,
+                                                               &rcv[1][1]);
+       pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_4,
+                                                               &rcv[2][0]);
+       pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_5,
+                                                               &rcv[2][1]);
+       for (i = 0 ; i < 3; i++) {
+               debugf3("MC_COR_ECC_CNT%d = 0x%x; MC_COR_ECC_CNT%d = 0x%x\n",
+                       (i * 2), rcv[i][0], (i * 2) + 1, rcv[i][1]);
+               /*if the channel has 3 dimms*/
+               if (pvt->channel[i].dimms > 2) {
+                       new0 = DIMM_BOT_COR_ERR(rcv[i][0]);
+                       new1 = DIMM_TOP_COR_ERR(rcv[i][0]);
+                       new2 = DIMM_BOT_COR_ERR(rcv[i][1]);
+               } else {
+                       new0 = DIMM_TOP_COR_ERR(rcv[i][0]) +
+                                       DIMM_BOT_COR_ERR(rcv[i][0]);
+                       new1 = DIMM_TOP_COR_ERR(rcv[i][1]) +
+                                       DIMM_BOT_COR_ERR(rcv[i][1]);
+                       new2 = 0;
+               }
+
+               i7core_rdimm_update_ce_count(mci, i, new0, new1, new2);
+       }
+}
+
+/* This function is based on the device 3 function 4 registers as described on:
+ * Intel Xeon Processor 5500 Series Datasheet Volume 2
+ *     http://www.intel.com/Assets/PDF/datasheet/321322.pdf
+ * also available at:
+ *     http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
+ */
+static void i7core_udimm_check_mc_ecc_err(struct mem_ctl_info *mci)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       u32 rcv1, rcv0;
+       int new0, new1, new2;
+
+       if (!pvt->pci_mcr[4]) {
+               debugf0("%s MCR registers not found\n", __func__);
+               return;
+       }
+
+       /* Corrected test errors */
+       pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV1, &rcv1);
+       pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV0, &rcv0);
+
+       /* Store the new values */
+       new2 = DIMM2_COR_ERR(rcv1);
+       new1 = DIMM1_COR_ERR(rcv0);
+       new0 = DIMM0_COR_ERR(rcv0);
+
+       /* Updates CE counters if it is not the first time here */
+       if (pvt->ce_count_available) {
+               /* Updates CE counters */
+               int add0, add1, add2;
+
+               add2 = new2 - pvt->udimm_last_ce_count[2];
+               add1 = new1 - pvt->udimm_last_ce_count[1];
+               add0 = new0 - pvt->udimm_last_ce_count[0];
+
+               if (add2 < 0)
+                       add2 += 0x7fff;
+               pvt->udimm_ce_count[2] += add2;
+
+               if (add1 < 0)
+                       add1 += 0x7fff;
+               pvt->udimm_ce_count[1] += add1;
+
+               if (add0 < 0)
+                       add0 += 0x7fff;
+               pvt->udimm_ce_count[0] += add0;
+
+               if (add0 | add1 | add2)
+                       i7core_printk(KERN_ERR, "New Corrected error(s): "
+                                     "dimm0: +%d, dimm1: +%d, dimm2 +%d\n",
+                                     add0, add1, add2);
+       } else
+               pvt->ce_count_available = 1;
+
+       /* Store the new values */
+       pvt->udimm_last_ce_count[2] = new2;
+       pvt->udimm_last_ce_count[1] = new1;
+       pvt->udimm_last_ce_count[0] = new0;
+}
+
+/*
+ * According with tables E-11 and E-12 of chapter E.3.3 of Intel 64 and IA-32
+ * Architectures Software Developer’s Manual Volume 3B.
+ * Nehalem are defined as family 0x06, model 0x1a
+ *
+ * The MCA registers used here are the following ones:
+ *     struct mce field        MCA Register
+ *     m->status       MSR_IA32_MC8_STATUS
+ *     m->addr         MSR_IA32_MC8_ADDR
+ *     m->misc         MSR_IA32_MC8_MISC
+ * In the case of Nehalem, the error information is masked at .status and .misc
+ * fields
+ */
+static void i7core_mce_output_error(struct mem_ctl_info *mci,
+                                   struct mce *m)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       char *type, *optype, *err, *msg;
+       unsigned long error = m->status & 0x1ff0000l;
+       u32 optypenum = (m->status >> 4) & 0x07;
+       u32 core_err_cnt = (m->status >> 38) && 0x7fff;
+       u32 dimm = (m->misc >> 16) & 0x3;
+       u32 channel = (m->misc >> 18) & 0x3;
+       u32 syndrome = m->misc >> 32;
+       u32 errnum = find_first_bit(&error, 32);
+       int csrow;
+
+       if (m->mcgstatus & 1)
+               type = "FATAL";
+       else
+               type = "NON_FATAL";
+
+       switch (optypenum) {
+       case 0:
+               optype = "generic undef request";
+               break;
+       case 1:
+               optype = "read error";
+               break;
+       case 2:
+               optype = "write error";
+               break;
+       case 3:
+               optype = "addr/cmd error";
+               break;
+       case 4:
+               optype = "scrubbing error";
+               break;
+       default:
+               optype = "reserved";
+               break;
+       }
+
+       switch (errnum) {
+       case 16:
+               err = "read ECC error";
+               break;
+       case 17:
+               err = "RAS ECC error";
+               break;
+       case 18:
+               err = "write parity error";
+               break;
+       case 19:
+               err = "redundacy loss";
+               break;
+       case 20:
+               err = "reserved";
+               break;
+       case 21:
+               err = "memory range error";
+               break;
+       case 22:
+               err = "RTID out of range";
+               break;
+       case 23:
+               err = "address parity error";
+               break;
+       case 24:
+               err = "byte enable parity error";
+               break;
+       default:
+               err = "unknown";
+       }
+
+       /* FIXME: should convert addr into bank and rank information */
+       msg = kasprintf(GFP_ATOMIC,
+               "%s (addr = 0x%08llx, cpu=%d, Dimm=%d, Channel=%d, "
+               "syndrome=0x%08x, count=%d, Err=%08llx:%08llx (%s: %s))\n",
+               type, (long long) m->addr, m->cpu, dimm, channel,
+               syndrome, core_err_cnt, (long long)m->status,
+               (long long)m->misc, optype, err);
+
+       debugf0("%s", msg);
+
+       csrow = pvt->csrow_map[channel][dimm];
+
+       /* Call the helper to output message */
+       if (m->mcgstatus & 1)
+               edac_mc_handle_fbd_ue(mci, csrow, 0,
+                               0 /* FIXME: should be channel here */, msg);
+       else if (!pvt->is_registered)
+               edac_mc_handle_fbd_ce(mci, csrow,
+                               0 /* FIXME: should be channel here */, msg);
+
+       kfree(msg);
+}
+
+/*
+ *     i7core_check_error      Retrieve and process errors reported by the
+ *                             hardware. Called by the Core module.
+ */
+static void i7core_check_error(struct mem_ctl_info *mci)
+{
+       struct i7core_pvt *pvt = mci->pvt_info;
+       int i;
+       unsigned count = 0;
+       struct mce *m;
+
+       /*
+        * MCE first step: Copy all mce errors into a temporary buffer
+        * We use a double buffering here, to reduce the risk of
+        * loosing an error.
+        */
+       smp_rmb();
+       count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in)
+               % MCE_LOG_LEN;
+       if (!count)
+               goto check_ce_error;
+
+       m = pvt->mce_outentry;
+       if (pvt->mce_in + count > MCE_LOG_LEN) {
+               unsigned l = MCE_LOG_LEN - pvt->mce_in;
+
+               memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l);
+               smp_wmb();
+               pvt->mce_in = 0;
+               count -= l;
+               m += l;
+       }
+       memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count);
+       smp_wmb();
+       pvt->mce_in += count;
+
+       smp_rmb();
+       if (pvt->mce_overrun) {
+               i7core_printk(KERN_ERR, "Lost %d memory errors\n",
+                             pvt->mce_overrun);
+               smp_wmb();
+               pvt->mce_overrun = 0;
+       }
+
+       /*
+        * MCE second step: parse errors and display
+        */
+       for (i = 0; i < count; i++)
+               i7core_mce_output_error(mci, &pvt->mce_outentry[i]);
+
+       /*
+        * Now, let's increment CE error counts
+        */
+check_ce_error:
+       if (!pvt->is_registered)
+               i7core_udimm_check_mc_ecc_err(mci);
+       else
+               i7core_rdimm_check_mc_ecc_err(mci);
+}
+
+/*
+ * i7core_mce_check_error      Replicates mcelog routine to get errors
+ *                             This routine simply queues mcelog errors, and
+ *                             return. The error itself should be handled later
+ *                             by i7core_check_error.
+ * WARNING: As this routine should be called at NMI time, extra care should
+ * be taken to avoid deadlocks, and to be as fast as possible.
+ */
+static int i7core_mce_check_error(void *priv, struct mce *mce)
+{
+       struct mem_ctl_info *mci = priv;
+       struct i7core_pvt *pvt = mci->pvt_info;
+
+       /*
+        * Just let mcelog handle it if the error is
+        * outside the memory controller
+        */
+       if (((mce->status & 0xffff) >> 7) != 1)
+               return 0;
+
+       /* Bank 8 registers are the only ones that we know how to handle */
+       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) {
+               smp_wmb();
+               pvt->mce_overrun++;
+               return 0;
+       }
+
+       /* Copy memory error at the ringbuffer */
+       memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce));
+       smp_wmb();
+       pvt->mce_out = (pvt->mce_out + 1) % MCE_LOG_LEN;
+
+       /* Handle fatal errors immediately */
+       if (mce->mcgstatus & 1)
+               i7core_check_error(mci);
+
+       /* Advice mcelog that the error were handled */
+       return 1;
+}
+
+static int i7core_register_mci(struct i7core_dev *i7core_dev,
+                              int num_channels, int num_csrows)
+{
+       struct mem_ctl_info *mci;
+       struct i7core_pvt *pvt;
+       int csrow = 0;
+       int rc;
+
+       /* allocate a new MC control structure */
+       mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels,
+                           i7core_dev->socket);
+       if (unlikely(!mci))
+               return -ENOMEM;
+
+       debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+       /* record ptr to the generic device */
+       mci->dev = &i7core_dev->pdev[0]->dev;
+
+       pvt = mci->pvt_info;
+       memset(pvt, 0, sizeof(*pvt));
+
+       /*
+        * FIXME: how to handle RDDR3 at MCI level? It is possible to have
+        * Mixed RDDR3/UDDR3 with Nehalem, provided that they are on different
+        * memory channels
+        */
+       mci->mtype_cap = MEM_FLAG_DDR3;
+       mci->edac_ctl_cap = EDAC_FLAG_NONE;
+       mci->edac_cap = EDAC_FLAG_NONE;
+       mci->mod_name = "i7core_edac.c";
+       mci->mod_ver = I7CORE_REVISION;
+       mci->ctl_name = kasprintf(GFP_KERNEL, "i7 core #%d",
+                                 i7core_dev->socket);
+       mci->dev_name = pci_name(i7core_dev->pdev[0]);
+       mci->ctl_page_to_phys = NULL;
+       mci->mc_driver_sysfs_attributes = i7core_sysfs_attrs;
+       /* Set the function pointer to an actual operation function */
+       mci->edac_check = i7core_check_error;
+
+       /* Store pci devices at mci for faster access */
+       rc = mci_bind_devs(mci, i7core_dev);
+       if (unlikely(rc < 0))
+               goto fail;
+
+       /* Get dimm basic config */
+       get_dimm_config(mci, &csrow);
+
+       /* add this new MC control structure to EDAC's list of MCs */
+       if (unlikely(edac_mc_add_mc(mci))) {
+               debugf0("MC: " __FILE__
+                       ": %s(): failed edac_mc_add_mc()\n", __func__);
+               /* FIXME: perhaps some code should go here that disables error
+                * reporting if we just enabled it
+                */
+
+               rc = -EINVAL;
+               goto fail;
+       }
+
+       /* allocating generic PCI control info */
+       i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
+                                                EDAC_MOD_STR);
+       if (unlikely(!i7core_pci)) {
+               printk(KERN_WARNING
+                       "%s(): Unable to create PCI control\n",
+                       __func__);
+               printk(KERN_WARNING
+                       "%s(): PCI error report via EDAC not setup\n",
+                       __func__);
+       }
+
+       /* Default error mask is any memory */
+       pvt->inject.channel = 0;
+       pvt->inject.dimm = -1;
+       pvt->inject.rank = -1;
+       pvt->inject.bank = -1;
+       pvt->inject.page = -1;
+       pvt->inject.col = -1;
+
+       /* Registers on edac_mce in order to receive memory errors */
+       pvt->edac_mce.priv = mci;
+       pvt->edac_mce.check_error = i7core_mce_check_error;
+
+       rc = edac_mce_register(&pvt->edac_mce);
+       if (unlikely(rc < 0)) {
+               debugf0("MC: " __FILE__
+                       ": %s(): failed edac_mce_register()\n", __func__);
+       }
+
+fail:
+       if (rc < 0)
+               edac_mc_free(mci);
+       return rc;
+}
+
+/*
+ *     i7core_probe    Probe for ONE instance of device to see if it is
+ *                     present.
+ *     return:
+ *             0 for FOUND a device
+ *             < 0 for error code
+ */
+
+static int probed = 0;
+
+static int __devinit i7core_probe(struct pci_dev *pdev,
+                                 const struct pci_device_id *id)
+{
+       int rc;
+       struct i7core_dev *i7core_dev;
+
+       /* get the pci devices we want to reserve for our use */
+       mutex_lock(&i7core_edac_lock);
+
+       /*
+        * All memory controllers are allocated at the first pass.
+        */
+       if (unlikely(probed >= 1)) {
+               mutex_unlock(&i7core_edac_lock);
+               return -EINVAL;
+       }
+       probed++;
+
+       rc = i7core_get_devices(pci_dev_table);
+       if (unlikely(rc < 0))
+               goto fail0;
+
+       list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
+               int channels;
+               int csrows;
+
+               /* Check the number of active and not disabled channels */
+               rc = i7core_get_active_channels(i7core_dev->socket,
+                                               &channels, &csrows);
+               if (unlikely(rc < 0))
+                       goto fail1;
+
+               rc = i7core_register_mci(i7core_dev, channels, csrows);
+               if (unlikely(rc < 0))
+                       goto fail1;
+       }
+
+       i7core_printk(KERN_INFO, "Driver loaded.\n");
+
+       mutex_unlock(&i7core_edac_lock);
+       return 0;
+
+fail1:
+       i7core_put_all_devices();
+fail0:
+       mutex_unlock(&i7core_edac_lock);
+       return rc;
+}
+
+/*
+ *     i7core_remove   destructor for one instance of device
+ *
+ */
+static void __devexit i7core_remove(struct pci_dev *pdev)
+{
+       struct mem_ctl_info *mci;
+       struct i7core_dev *i7core_dev, *tmp;
+
+       debugf0(__FILE__ ": %s()\n", __func__);
+
+       if (i7core_pci)
+               edac_pci_release_generic_ctl(i7core_pci);
+
+       /*
+        * we have a trouble here: pdev value for removal will be wrong, since
+        * it will point to the X58 register used to detect that the machine
+        * is a Nehalem or upper design. However, due to the way several PCI
+        * devices are grouped together to provide MC functionality, we need
+        * to use a different method for releasing the devices
+        */
+
+       mutex_lock(&i7core_edac_lock);
+       list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
+               mci = edac_mc_del_mc(&i7core_dev->pdev[0]->dev);
+               if (mci) {
+                       struct i7core_pvt *pvt = mci->pvt_info;
+
+                       i7core_dev = pvt->i7core_dev;
+                       edac_mce_unregister(&pvt->edac_mce);
+                       kfree(mci->ctl_name);
+                       edac_mc_free(mci);
+                       i7core_put_devices(i7core_dev);
+               } else {
+                       i7core_printk(KERN_ERR,
+                                     "Couldn't find mci for socket %d\n",
+                                     i7core_dev->socket);
+               }
+       }
+       probed--;
+
+       mutex_unlock(&i7core_edac_lock);
+}
+
+MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);
+
+/*
+ *     i7core_driver   pci_driver structure for this module
+ *
+ */
+static struct pci_driver i7core_driver = {
+       .name     = "i7core_edac",
+       .probe    = i7core_probe,
+       .remove   = __devexit_p(i7core_remove),
+       .id_table = i7core_pci_tbl,
+};
+
+/*
+ *     i7core_init             Module entry function
+ *                     Try to initialize this module for its devices
+ */
+static int __init i7core_init(void)
+{
+       int pci_rc;
+
+       debugf2("MC: " __FILE__ ": %s()\n", __func__);
+
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
+       i7core_xeon_pci_fixup(pci_dev_table);
+
+       pci_rc = pci_register_driver(&i7core_driver);
+
+       if (pci_rc >= 0)
+               return 0;
+
+       i7core_printk(KERN_ERR, "Failed to register device with error %d.\n",
+                     pci_rc);
+
+       return pci_rc;
+}
+
+/*
+ *     i7core_exit()   Module exit function
+ *                     Unregister the driver
+ */
+static void __exit i7core_exit(void)
+{
+       debugf2("MC: " __FILE__ ": %s()\n", __func__);
+       pci_unregister_driver(&i7core_driver);
+}
+
+module_init(i7core_init);
+module_exit(i7core_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("MC Driver for Intel i7 Core memory controllers - "
+                  I7CORE_REVISION);
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
index 6c1886b497ff673add09b99809f065c9a294090b..52ca09bf4726ae9cb5984d38c79d86705c5b51f8 100644 (file)
@@ -229,7 +229,7 @@ static int __devinit mpc85xx_pci_err_probe(struct of_device *op,
 
        pdata->edac_idx = edac_pci_idx++;
 
-       res = of_address_to_resource(op->node, 0, &r);
+       res = of_address_to_resource(op->dev.of_node, 0, &r);
        if (res) {
                printk(KERN_ERR "%s: Unable to get resource for "
                       "PCI err regs\n", __func__);
@@ -274,7 +274,7 @@ static int __devinit mpc85xx_pci_err_probe(struct of_device *op,
        }
 
        if (edac_op_state == EDAC_OPSTATE_INT) {
-               pdata->irq = irq_of_parse_and_map(op->node, 0);
+               pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
                res = devm_request_irq(&op->dev, pdata->irq,
                                       mpc85xx_pci_isr, IRQF_DISABLED,
                                       "[EDAC] PCI err", pci);
@@ -529,7 +529,7 @@ static int __devinit mpc85xx_l2_err_probe(struct of_device *op,
        edac_dev->ctl_name = pdata->name;
        edac_dev->dev_name = pdata->name;
 
-       res = of_address_to_resource(op->node, 0, &r);
+       res = of_address_to_resource(op->dev.of_node, 0, &r);
        if (res) {
                printk(KERN_ERR "%s: Unable to get resource for "
                       "L2 err regs\n", __func__);
@@ -576,7 +576,7 @@ static int __devinit mpc85xx_l2_err_probe(struct of_device *op,
        }
 
        if (edac_op_state == EDAC_OPSTATE_INT) {
-               pdata->irq = irq_of_parse_and_map(op->node, 0);
+               pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
                res = devm_request_irq(&op->dev, pdata->irq,
                                       mpc85xx_l2_isr, IRQF_DISABLED,
                                       "[EDAC] L2 err", edac_dev);
@@ -978,7 +978,7 @@ static int __devinit mpc85xx_mc_err_probe(struct of_device *op,
        mci->ctl_name = pdata->name;
        mci->dev_name = pdata->name;
 
-       res = of_address_to_resource(op->node, 0, &r);
+       res = of_address_to_resource(op->dev.of_node, 0, &r);
        if (res) {
                printk(KERN_ERR "%s: Unable to get resource for MC err regs\n",
                       __func__);
@@ -1052,7 +1052,7 @@ static int __devinit mpc85xx_mc_err_probe(struct of_device *op,
                out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, 0x10000);
 
                /* register interrupts */
-               pdata->irq = irq_of_parse_and_map(op->node, 0);
+               pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
                res = devm_request_irq(&op->dev, pdata->irq,
                                       mpc85xx_mc_isr,
                                        IRQF_DISABLED | IRQF_SHARED,
index 9d6f6783328c80357cb794614ff79dca1e0b84d0..e78839e89a067400726b26a302eb05f317200b02 100644 (file)
@@ -1022,7 +1022,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
        int status = 0;
        const u32 memcheck = (mcopt1 & SDRAM_MCOPT1_MCHK_MASK);
        struct ppc4xx_edac_pdata *pdata = NULL;
-       const struct device_node *np = op->node;
+       const struct device_node *np = op->dev.of_node;
 
        if (match == NULL)
                return -EINVAL;
@@ -1113,7 +1113,7 @@ ppc4xx_edac_register_irq(struct of_device *op, struct mem_ctl_info *mci)
        int status = 0;
        int ded_irq, sec_irq;
        struct ppc4xx_edac_pdata *pdata = mci->pvt_info;
-       struct device_node *np = op->node;
+       struct device_node *np = op->dev.of_node;
 
        ded_irq = irq_of_parse_and_map(np, INTMAP_ECCDED_INDEX);
        sec_irq = irq_of_parse_and_map(np, INTMAP_ECCSEC_INDEX);
@@ -1243,7 +1243,7 @@ ppc4xx_edac_probe(struct of_device *op, const struct of_device_id *match)
        int status = 0;
        u32 mcopt1, memcheck;
        dcr_host_t dcr_host;
-       const struct device_node *np = op->node;
+       const struct device_node *np = op->dev.of_node;
        struct mem_ctl_info *mci = NULL;
        static int ppc4xx_edac_instance;
 
index 9dcb30466ec0a22a11092decb65474e7bdcc5191..371713ff02660e0c0ab08bf86a3d496f90a6e718 100644 (file)
@@ -231,7 +231,7 @@ void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
 static void fw_card_bm_work(struct work_struct *work)
 {
        struct fw_card *card = container_of(work, struct fw_card, work.work);
-       struct fw_device *root_device;
+       struct fw_device *root_device, *irm_device;
        struct fw_node *root_node;
        unsigned long flags;
        int root_id, new_root_id, irm_id, local_id;
@@ -239,6 +239,7 @@ static void fw_card_bm_work(struct work_struct *work)
        bool do_reset = false;
        bool root_device_is_running;
        bool root_device_is_cmc;
+       bool irm_is_1394_1995_only;
 
        spin_lock_irqsave(&card->lock, flags);
 
@@ -248,12 +249,18 @@ static void fw_card_bm_work(struct work_struct *work)
        }
 
        generation = card->generation;
+
        root_node = card->root_node;
        fw_node_get(root_node);
        root_device = root_node->data;
        root_device_is_running = root_device &&
                        atomic_read(&root_device->state) == FW_DEVICE_RUNNING;
        root_device_is_cmc = root_device && root_device->cmc;
+
+       irm_device = card->irm_node->data;
+       irm_is_1394_1995_only = irm_device && irm_device->config_rom &&
+                       (irm_device->config_rom[2] & 0x000000f0) == 0;
+
        root_id  = root_node->node_id;
        irm_id   = card->irm_node->node_id;
        local_id = card->local_node->node_id;
@@ -276,8 +283,15 @@ static void fw_card_bm_work(struct work_struct *work)
 
                if (!card->irm_node->link_on) {
                        new_root_id = local_id;
-                       fw_notify("IRM has link off, making local node (%02x) root.\n",
-                                 new_root_id);
+                       fw_notify("%s, making local node (%02x) root.\n",
+                                 "IRM has link off", new_root_id);
+                       goto pick_me;
+               }
+
+               if (irm_is_1394_1995_only) {
+                       new_root_id = local_id;
+                       fw_notify("%s, making local node (%02x) root.\n",
+                                 "IRM is not 1394a compliant", new_root_id);
                        goto pick_me;
                }
 
@@ -316,8 +330,8 @@ static void fw_card_bm_work(struct work_struct *work)
                         * root, and thus, IRM.
                         */
                        new_root_id = local_id;
-                       fw_notify("BM lock failed, making local node (%02x) root.\n",
-                                 new_root_id);
+                       fw_notify("%s, making local node (%02x) root.\n",
+                                 "BM lock failed", new_root_id);
                        goto pick_me;
                }
        } else if (card->bm_generation != generation) {
index 724038dab4caa72db78309def86ec448f259407d..7face915b963fe62a6940beccde71058a23111c4 100644 (file)
@@ -1,5 +1,5 @@
 #
-# GPIO infrastructure and expanders
+# platform-neutral GPIO infrastructure and expanders
 #
 
 config ARCH_WANT_OPTIONAL_GPIOLIB
index 51c3cdd41b5aac95514b41e58c105208ba278e60..e53dcff49b4f650765c4f1f1017a45664feb3ccc 100644 (file)
@@ -1,4 +1,8 @@
-# gpio support: dedicated expander chips, etc
+# generic gpio support: dedicated expander chips, etc
+#
+# NOTE: platform-specific GPIO drivers don't belong in the
+# drivers/gpio directory; put them with other platform setup
+# code, IRQ controllers, board init, etc.
 
 ccflags-$(CONFIG_DEBUG_GPIO)   += -DDEBUG
 
index 994d23beeb1d68dce7032abf5cc347c4f3027c44..57cea01c4ffb25cb62b7b46007853c506a5c15a3 100644 (file)
@@ -1840,8 +1840,10 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
 
                ret = copy_from_user(clips, clips_ptr,
                                     num_clips * sizeof(*clips));
-               if (ret)
+               if (ret) {
+                       ret = -EFAULT;
                        goto out_err2;
+               }
        }
 
        if (fb->funcs->dirty) {
index 764401951041910692901ea9c1489962de3277b8..9b2a54117c91c0a306c41c7eb437b641bbd58b31 100644 (file)
@@ -860,19 +860,24 @@ static void output_poll_execute(struct slow_work *work)
        }
 }
 
-void drm_kms_helper_poll_init(struct drm_device *dev)
+void drm_kms_helper_poll_disable(struct drm_device *dev)
+{
+       if (!dev->mode_config.poll_enabled)
+               return;
+       delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
+}
+EXPORT_SYMBOL(drm_kms_helper_poll_disable);
+
+void drm_kms_helper_poll_enable(struct drm_device *dev)
 {
-       struct drm_connector *connector;
        bool poll = false;
+       struct drm_connector *connector;
        int ret;
 
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                if (connector->polled)
                        poll = true;
        }
-       slow_work_register_user(THIS_MODULE);
-       delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
-                              &output_poll_ops);
 
        if (poll) {
                ret = delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, DRM_OUTPUT_POLL_PERIOD);
@@ -880,11 +885,22 @@ void drm_kms_helper_poll_init(struct drm_device *dev)
                        DRM_ERROR("delayed enqueue failed %d\n", ret);
        }
 }
+EXPORT_SYMBOL(drm_kms_helper_poll_enable);
+
+void drm_kms_helper_poll_init(struct drm_device *dev)
+{
+       slow_work_register_user(THIS_MODULE);
+       delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
+                              &output_poll_ops);
+       dev->mode_config.poll_enabled = true;
+
+       drm_kms_helper_poll_enable(dev);
+}
 EXPORT_SYMBOL(drm_kms_helper_poll_init);
 
 void drm_kms_helper_poll_fini(struct drm_device *dev)
 {
-       delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
+       drm_kms_helper_poll_disable(dev);
        slow_work_unregister_user(THIS_MODULE);
 }
 EXPORT_SYMBOL(drm_kms_helper_poll_fini);
index b3779d243aefc30f48768c67c2f5a261dd825ce2..1f2cc6b09623cd8b3d2677ecf11277b678bba891 100644 (file)
@@ -146,7 +146,7 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_conn
                                cvt = 1;
                        break;
                case 'R':
-                       if (!cvt)
+                       if (cvt)
                                rb = 1;
                        break;
                case 'm':
@@ -264,7 +264,7 @@ bool drm_fb_helper_force_kernel_mode(void)
 int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
                        void *panic_str)
 {
-       DRM_ERROR("panic occurred, switching back to text console\n");
+       printk(KERN_ERR "panic occurred, switching back to text console\n");
        return drm_fb_helper_force_kernel_mode();
        return 0;
 }
@@ -1024,11 +1024,18 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne
        }
 
 create_mode:
-       mode = drm_cvt_mode(fb_helper_conn->connector->dev, cmdline_mode->xres,
-                           cmdline_mode->yres,
-                           cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
-                           cmdline_mode->rb, cmdline_mode->interlace,
-                           cmdline_mode->margins);
+       if (cmdline_mode->cvt)
+               mode = drm_cvt_mode(fb_helper_conn->connector->dev,
+                                   cmdline_mode->xres, cmdline_mode->yres,
+                                   cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
+                                   cmdline_mode->rb, cmdline_mode->interlace,
+                                   cmdline_mode->margins);
+       else
+               mode = drm_gtf_mode(fb_helper_conn->connector->dev,
+                                   cmdline_mode->xres, cmdline_mode->yres,
+                                   cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
+                                   cmdline_mode->interlace,
+                                   cmdline_mode->margins);
        drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
        list_add(&mode->head, &fb_helper_conn->connector->modes);
        return mode;
index 95639017bdbe732ef9765f28905189966bb77182..da78f2c0d90949b57b067d97a038a324337bb65e 100644 (file)
@@ -22,6 +22,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
          intel_fb.o \
          intel_tv.o \
          intel_dvo.o \
+         intel_ringbuffer.o \
          intel_overlay.o \
          dvo_ch7xxx.o \
          dvo_ch7017.o \
index 66c697bc9b2274abb8701ffa63a42b1782bb3297..56f66426207f0a1a293dcb073360985d328fd85e 100644 (file)
@@ -208,7 +208,7 @@ static enum drm_connector_status tfp410_detect(struct intel_dvo_device *dvo)
        uint8_t ctl2;
 
        if (tfp410_readb(dvo, TFP410_CTL_2, &ctl2)) {
-               if (ctl2 & TFP410_CTL_2_HTPLG)
+               if (ctl2 & TFP410_CTL_2_RSEN)
                        ret = connector_status_connected;
                else
                        ret = connector_status_disconnected;
index 322070c0c631966afe72abdc2113f67aa787a0e4..aee83fa178f6a6dc60c7273eaaae29b43dbe000d 100644 (file)
@@ -77,7 +77,7 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
        case ACTIVE_LIST:
                seq_printf(m, "Active:\n");
                lock = &dev_priv->mm.active_list_lock;
-               head = &dev_priv->mm.active_list;
+               head = &dev_priv->render_ring.active_list;
                break;
        case INACTIVE_LIST:
                seq_printf(m, "Inactive:\n");
@@ -129,7 +129,8 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
        struct drm_i915_gem_request *gem_request;
 
        seq_printf(m, "Request:\n");
-       list_for_each_entry(gem_request, &dev_priv->mm.request_list, list) {
+       list_for_each_entry(gem_request, &dev_priv->render_ring.request_list,
+                       list) {
                seq_printf(m, "    %d @ %d\n",
                           gem_request->seqno,
                           (int) (jiffies - gem_request->emitted_jiffies));
@@ -143,9 +144,9 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
 
-       if (dev_priv->hw_status_page != NULL) {
+       if (dev_priv->render_ring.status_page.page_addr != NULL) {
                seq_printf(m, "Current sequence: %d\n",
-                          i915_get_gem_seqno(dev));
+                          i915_get_gem_seqno(dev,  &dev_priv->render_ring));
        } else {
                seq_printf(m, "Current sequence: hws uninitialized\n");
        }
@@ -195,9 +196,9 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
        }
        seq_printf(m, "Interrupts received: %d\n",
                   atomic_read(&dev_priv->irq_received));
-       if (dev_priv->hw_status_page != NULL) {
+       if (dev_priv->render_ring.status_page.page_addr != NULL) {
                seq_printf(m, "Current sequence:    %d\n",
-                          i915_get_gem_seqno(dev));
+                          i915_get_gem_seqno(dev,  &dev_priv->render_ring));
        } else {
                seq_printf(m, "Current sequence:    hws uninitialized\n");
        }
@@ -251,7 +252,7 @@ static int i915_hws_info(struct seq_file *m, void *data)
        int i;
        volatile u32 *hws;
 
-       hws = (volatile u32 *)dev_priv->hw_status_page;
+       hws = (volatile u32 *)dev_priv->render_ring.status_page.page_addr;
        if (hws == NULL)
                return 0;
 
@@ -287,7 +288,8 @@ static int i915_batchbuffer_info(struct seq_file *m, void *data)
 
        spin_lock(&dev_priv->mm.active_list_lock);
 
-       list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
+       list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list,
+                       list) {
                obj = &obj_priv->base;
                if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) {
                    ret = i915_gem_object_get_pages(obj, 0);
@@ -317,14 +319,14 @@ static int i915_ringbuffer_data(struct seq_file *m, void *data)
        u8 *virt;
        uint32_t *ptr, off;
 
-       if (!dev_priv->ring.ring_obj) {
+       if (!dev_priv->render_ring.gem_object) {
                seq_printf(m, "No ringbuffer setup\n");
                return 0;
        }
 
-       virt = dev_priv->ring.virtual_start;
+       virt = dev_priv->render_ring.virtual_start;
 
-       for (off = 0; off < dev_priv->ring.Size; off += 4) {
+       for (off = 0; off < dev_priv->render_ring.size; off += 4) {
                ptr = (uint32_t *)(virt + off);
                seq_printf(m, "%08x :  %08x\n", off, *ptr);
        }
@@ -344,7 +346,7 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
 
        seq_printf(m, "RingHead :  %08x\n", head);
        seq_printf(m, "RingTail :  %08x\n", tail);
-       seq_printf(m, "RingSize :  %08lx\n", dev_priv->ring.Size);
+       seq_printf(m, "RingSize :  %08lx\n", dev_priv->render_ring.size);
        seq_printf(m, "Acthd :     %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
 
        return 0;
@@ -489,11 +491,14 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        u16 rgvswctl = I915_READ16(MEMSWCTL);
+       u16 rgvstat = I915_READ16(MEMSTAT_ILK);
 
-       seq_printf(m, "Last command: 0x%01x\n", (rgvswctl >> 13) & 0x3);
-       seq_printf(m, "Command status: %d\n", (rgvswctl >> 12) & 1);
-       seq_printf(m, "P%d DELAY 0x%02x\n", (rgvswctl >> 8) & 0xf,
-                  rgvswctl & 0x3f);
+       seq_printf(m, "Requested P-state: %d\n", (rgvswctl >> 8) & 0xf);
+       seq_printf(m, "Requested VID: %d\n", rgvswctl & 0x3f);
+       seq_printf(m, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK) >>
+                  MEMSTAT_VID_SHIFT);
+       seq_printf(m, "Current P-state: %d\n",
+                  (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
 
        return 0;
 }
@@ -508,7 +513,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
 
        for (i = 0; i < 16; i++) {
                delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
-               seq_printf(m, "P%02dVIDFREQ: 0x%08x\n", i, delayfreq);
+               seq_printf(m, "P%02dVIDFREQ: 0x%08x (VID: %d)\n", i, delayfreq,
+                          (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
        }
 
        return 0;
@@ -541,6 +547,8 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 rgvmodectl = I915_READ(MEMMODECTL);
+       u32 rstdbyctl = I915_READ(MCHBAR_RENDER_STANDBY);
+       u16 crstandvid = I915_READ16(CRSTANDVID);
 
        seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
                   "yes" : "no");
@@ -555,9 +563,13 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
                   rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no");
        seq_printf(m, "Starting frequency: P%d\n",
                   (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT);
-       seq_printf(m, "Max frequency: P%d\n",
+       seq_printf(m, "Max P-state: P%d\n",
                   (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT);
-       seq_printf(m, "Min frequency: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK));
+       seq_printf(m, "Min P-state: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK));
+       seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f));
+       seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
+       seq_printf(m, "Render standby enabled: %s\n",
+                  (rstdbyctl & RCX_SW_EXIT) ? "no" : "yes");
 
        return 0;
 }
@@ -608,7 +620,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
        drm_i915_private_t *dev_priv = dev->dev_private;
        bool sr_enabled = false;
 
-       if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev))
+       if (IS_I965GM(dev) || IS_I945G(dev) || IS_I945GM(dev))
                sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
        else if (IS_I915GM(dev))
                sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
@@ -621,6 +633,36 @@ static int i915_sr_status(struct seq_file *m, void *unused)
        return 0;
 }
 
+static int i915_emon_status(struct seq_file *m, void *unused)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       unsigned long temp, chipset, gfx;
+
+       temp = i915_mch_val(dev_priv);
+       chipset = i915_chipset_val(dev_priv);
+       gfx = i915_gfx_val(dev_priv);
+
+       seq_printf(m, "GMCH temp: %ld\n", temp);
+       seq_printf(m, "Chipset power: %ld\n", chipset);
+       seq_printf(m, "GFX power: %ld\n", gfx);
+       seq_printf(m, "Total power: %ld\n", chipset + gfx);
+
+       return 0;
+}
+
+static int i915_gfxec(struct seq_file *m, void *unused)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+
+       seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
+
+       return 0;
+}
+
 static int
 i915_wedged_open(struct inode *inode,
                 struct file *filp)
@@ -743,6 +785,8 @@ static struct drm_info_list i915_debugfs_list[] = {
        {"i915_delayfreq_table", i915_delayfreq_table, 0},
        {"i915_inttoext_table", i915_inttoext_table, 0},
        {"i915_drpc_info", i915_drpc_info, 0},
+       {"i915_emon_status", i915_emon_status, 0},
+       {"i915_gfxec", i915_gfxec, 0},
        {"i915_fbc_status", i915_fbc_status, 0},
        {"i915_sr_status", i915_sr_status, 0},
 };
index 2a6b5de5ae5d07330232b8aff6b0b989300147a2..f00c5ae9556ccb47358ce1f5267dd9cc5cb17a21 100644 (file)
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 
-/* Really want an OS-independent resettable timer.  Would like to have
- * this loop run for (eg) 3 sec, but have the timer reset every time
- * the head pointer changes, so that EBUSY only happens if the ring
- * actually stalls for (eg) 3 seconds.
- */
-int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
-       u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
-       u32 last_acthd = I915_READ(acthd_reg);
-       u32 acthd;
-       u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-       int i;
-
-       trace_i915_ring_wait_begin (dev);
-
-       for (i = 0; i < 100000; i++) {
-               ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-               acthd = I915_READ(acthd_reg);
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->Size;
-               if (ring->space >= n) {
-                       trace_i915_ring_wait_end (dev);
-                       return 0;
-               }
-
-               if (dev->primary->master) {
-                       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-                       if (master_priv->sarea_priv)
-                               master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-               }
-
-
-               if (ring->head != last_head)
-                       i = 0;
-               if (acthd != last_acthd)
-                       i = 0;
-
-               last_head = ring->head;
-               last_acthd = acthd;
-               msleep_interruptible(10);
-
-       }
-
-       trace_i915_ring_wait_end (dev);
-       return -EBUSY;
-}
-
-/* As a ringbuffer is only allowed to wrap between instructions, fill
- * the tail with NOOPs.
- */
-int i915_wrap_ring(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       volatile unsigned int *virt;
-       int rem;
-
-       rem = dev_priv->ring.Size - dev_priv->ring.tail;
-       if (dev_priv->ring.space < rem) {
-               int ret = i915_wait_ring(dev, rem, __func__);
-               if (ret)
-                       return ret;
-       }
-       dev_priv->ring.space -= rem;
-
-       virt = (unsigned int *)
-               (dev_priv->ring.virtual_start + dev_priv->ring.tail);
-       rem /= 4;
-       while (rem--)
-               *virt++ = MI_NOOP;
-
-       dev_priv->ring.tail = 0;
-
-       return 0;
-}
-
 /**
  * Sets up the hardware status page for devices that need a physical address
  * in the register.
@@ -133,10 +55,11 @@ static int i915_init_phys_hws(struct drm_device *dev)
                DRM_ERROR("Can not allocate hardware status page\n");
                return -ENOMEM;
        }
-       dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+       dev_priv->render_ring.status_page.page_addr
+               = dev_priv->status_page_dmah->vaddr;
        dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
 
-       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+       memset(dev_priv->render_ring.status_page.page_addr, 0, PAGE_SIZE);
 
        if (IS_I965G(dev))
                dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) &
@@ -159,8 +82,8 @@ static void i915_free_hws(struct drm_device *dev)
                dev_priv->status_page_dmah = NULL;
        }
 
-       if (dev_priv->status_gfx_addr) {
-               dev_priv->status_gfx_addr = 0;
+       if (dev_priv->render_ring.status_page.gfx_addr) {
+               dev_priv->render_ring.status_page.gfx_addr = 0;
                drm_core_ioremapfree(&dev_priv->hws_map, dev);
        }
 
@@ -172,7 +95,7 @@ void i915_kernel_lost_context(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_master_private *master_priv;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+       struct intel_ring_buffer *ring = &dev_priv->render_ring;
 
        /*
         * We should never lose context on the ring with modesetting
@@ -185,7 +108,7 @@ void i915_kernel_lost_context(struct drm_device * dev)
        ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
        ring->space = ring->head - (ring->tail + 8);
        if (ring->space < 0)
-               ring->space += ring->Size;
+               ring->space += ring->size;
 
        if (!dev->primary->master)
                return;
@@ -205,12 +128,11 @@ static int i915_dma_cleanup(struct drm_device * dev)
        if (dev->irq_enabled)
                drm_irq_uninstall(dev);
 
-       if (dev_priv->ring.virtual_start) {
-               drm_core_ioremapfree(&dev_priv->ring.map, dev);
-               dev_priv->ring.virtual_start = NULL;
-               dev_priv->ring.map.handle = NULL;
-               dev_priv->ring.map.size = 0;
-       }
+       mutex_lock(&dev->struct_mutex);
+       intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
+       if (HAS_BSD(dev))
+               intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
+       mutex_unlock(&dev->struct_mutex);
 
        /* Clear the HWS virtual address at teardown */
        if (I915_NEED_GFX_HWS(dev))
@@ -233,24 +155,24 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
        }
 
        if (init->ring_size != 0) {
-               if (dev_priv->ring.ring_obj != NULL) {
+               if (dev_priv->render_ring.gem_object != NULL) {
                        i915_dma_cleanup(dev);
                        DRM_ERROR("Client tried to initialize ringbuffer in "
                                  "GEM mode\n");
                        return -EINVAL;
                }
 
-               dev_priv->ring.Size = init->ring_size;
+               dev_priv->render_ring.size = init->ring_size;
 
-               dev_priv->ring.map.offset = init->ring_start;
-               dev_priv->ring.map.size = init->ring_size;
-               dev_priv->ring.map.type = 0;
-               dev_priv->ring.map.flags = 0;
-               dev_priv->ring.map.mtrr = 0;
+               dev_priv->render_ring.map.offset = init->ring_start;
+               dev_priv->render_ring.map.size = init->ring_size;
+               dev_priv->render_ring.map.type = 0;
+               dev_priv->render_ring.map.flags = 0;
+               dev_priv->render_ring.map.mtrr = 0;
 
-               drm_core_ioremap_wc(&dev_priv->ring.map, dev);
+               drm_core_ioremap_wc(&dev_priv->render_ring.map, dev);
 
-               if (dev_priv->ring.map.handle == NULL) {
+               if (dev_priv->render_ring.map.handle == NULL) {
                        i915_dma_cleanup(dev);
                        DRM_ERROR("can not ioremap virtual address for"
                                  " ring buffer\n");
@@ -258,7 +180,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
                }
        }
 
-       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+       dev_priv->render_ring.virtual_start = dev_priv->render_ring.map.handle;
 
        dev_priv->cpp = init->cpp;
        dev_priv->back_offset = init->back_offset;
@@ -278,26 +200,29 @@ static int i915_dma_resume(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
+       struct intel_ring_buffer *ring;
        DRM_DEBUG_DRIVER("%s\n", __func__);
 
-       if (dev_priv->ring.map.handle == NULL) {
+       ring = &dev_priv->render_ring;
+
+       if (ring->map.handle == NULL) {
                DRM_ERROR("can not ioremap virtual address for"
                          " ring buffer\n");
                return -ENOMEM;
        }
 
        /* Program Hardware Status Page */
-       if (!dev_priv->hw_status_page) {
+       if (!ring->status_page.page_addr) {
                DRM_ERROR("Can not find hardware status page\n");
                return -EINVAL;
        }
        DRM_DEBUG_DRIVER("hw status page @ %p\n",
-                               dev_priv->hw_status_page);
-
-       if (dev_priv->status_gfx_addr != 0)
-               I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
+                               ring->status_page.page_addr);
+       if (ring->status_page.gfx_addr != 0)
+               ring->setup_status_page(dev, ring);
        else
                I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
+
        DRM_DEBUG_DRIVER("Enabled hardware status page\n");
 
        return 0;
@@ -407,9 +332,8 @@ static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        int i;
-       RING_LOCALS;
 
-       if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
+       if ((dwords+1) * sizeof(int) >= dev_priv->render_ring.size - 8)
                return -EINVAL;
 
        BEGIN_LP_RING((dwords+1)&~1);
@@ -442,9 +366,7 @@ i915_emit_box(struct drm_device *dev,
              struct drm_clip_rect *boxes,
              int i, int DR1, int DR4)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_clip_rect box = boxes[i];
-       RING_LOCALS;
 
        if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
                DRM_ERROR("Bad box %d,%d..%d,%d\n",
@@ -481,7 +403,6 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-       RING_LOCALS;
 
        dev_priv->counter++;
        if (dev_priv->counter > 0x7FFFFFFFUL)
@@ -535,10 +456,8 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
                                     drm_i915_batchbuffer_t * batch,
                                     struct drm_clip_rect *cliprects)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
        int nbox = batch->num_cliprects;
        int i = 0, count;
-       RING_LOCALS;
 
        if ((batch->start | batch->used) & 0x7) {
                DRM_ERROR("alignment");
@@ -587,7 +506,6 @@ static int i915_dispatch_flip(struct drm_device * dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_master_private *master_priv =
                dev->primary->master->driver_priv;
-       RING_LOCALS;
 
        if (!master_priv->sarea_priv)
                return -EINVAL;
@@ -640,7 +558,8 @@ static int i915_quiescent(struct drm_device * dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
 
        i915_kernel_lost_context(dev);
-       return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
+       return intel_wait_ring_buffer(dev, &dev_priv->render_ring,
+                                     dev_priv->render_ring.size - 8);
 }
 
 static int i915_flush_ioctl(struct drm_device *dev, void *data,
@@ -827,6 +746,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
                /* depends on GEM */
                value = dev_priv->has_gem;
                break;
+       case I915_PARAM_HAS_BSD:
+               value = HAS_BSD(dev);
+               break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
                                 param->param);
@@ -882,6 +804,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        drm_i915_hws_addr_t *hws = data;
+       struct intel_ring_buffer *ring = &dev_priv->render_ring;
 
        if (!I915_NEED_GFX_HWS(dev))
                return -EINVAL;
@@ -898,7 +821,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
 
        DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr);
 
-       dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
+       ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12);
 
        dev_priv->hws_map.offset = dev->agp->base + hws->addr;
        dev_priv->hws_map.size = 4*1024;
@@ -909,19 +832,19 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
        drm_core_ioremap_wc(&dev_priv->hws_map, dev);
        if (dev_priv->hws_map.handle == NULL) {
                i915_dma_cleanup(dev);
-               dev_priv->status_gfx_addr = 0;
+               ring->status_page.gfx_addr = 0;
                DRM_ERROR("can not ioremap virtual address for"
                                " G33 hw status page\n");
                return -ENOMEM;
        }
-       dev_priv->hw_status_page = dev_priv->hws_map.handle;
+       ring->status_page.page_addr = dev_priv->hws_map.handle;
+       memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+       I915_WRITE(HWS_PGA, ring->status_page.gfx_addr);
 
-       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-       I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
        DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n",
-                               dev_priv->status_gfx_addr);
+                        ring->status_page.gfx_addr);
        DRM_DEBUG_DRIVER("load hws at %p\n",
-                               dev_priv->hw_status_page);
+                        ring->status_page.page_addr);
        return 0;
 }
 
@@ -1308,7 +1231,7 @@ static void i915_warn_stolen(struct drm_device *dev)
 static void i915_setup_compression(struct drm_device *dev, int size)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_mm_node *compressed_fb, *compressed_llb;
+       struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
        unsigned long cfb_base;
        unsigned long ll_base = 0;
 
@@ -1399,12 +1322,14 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
        struct drm_device *dev = pci_get_drvdata(pdev);
        pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
        if (state == VGA_SWITCHEROO_ON) {
-               printk(KERN_INFO "i915: switched off\n");
+               printk(KERN_INFO "i915: switched on\n");
                /* i915 resume handler doesn't set to D0 */
                pci_set_power_state(dev->pdev, PCI_D0);
                i915_resume(dev);
+               drm_kms_helper_poll_enable(dev);
        } else {
                printk(KERN_ERR "i915: switched off\n");
+               drm_kms_helper_poll_disable(dev);
                i915_suspend(dev, pmm);
        }
 }
@@ -1479,19 +1404,23 @@ static int i915_load_modeset_init(struct drm_device *dev,
        /* if we have > 1 VGA cards, then disable the radeon VGA resources */
        ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
        if (ret)
-               goto destroy_ringbuffer;
+               goto cleanup_ringbuffer;
 
        ret = vga_switcheroo_register_client(dev->pdev,
                                             i915_switcheroo_set_state,
                                             i915_switcheroo_can_switch);
        if (ret)
-               goto destroy_ringbuffer;
+               goto cleanup_vga_client;
+
+       /* IIR "flip pending" bit means done if this bit is set */
+       if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
+               dev_priv->flip_pending_is_done = true;
 
        intel_modeset_init(dev);
 
        ret = drm_irq_install(dev);
        if (ret)
-               goto destroy_ringbuffer;
+               goto cleanup_vga_switcheroo;
 
        /* Always safe in the mode setting case. */
        /* FIXME: do pre/post-mode set stuff in core KMS code */
@@ -1503,11 +1432,20 @@ static int i915_load_modeset_init(struct drm_device *dev,
 
        I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
 
-       intel_fbdev_init(dev);
+       ret = intel_fbdev_init(dev);
+       if (ret)
+               goto cleanup_irq;
+
        drm_kms_helper_poll_init(dev);
        return 0;
 
-destroy_ringbuffer:
+cleanup_irq:
+       drm_irq_uninstall(dev);
+cleanup_vga_switcheroo:
+       vga_switcheroo_unregister_client(dev->pdev);
+cleanup_vga_client:
+       vga_client_register(dev->pdev, NULL, NULL, NULL);
+cleanup_ringbuffer:
        mutex_lock(&dev->struct_mutex);
        i915_gem_cleanup_ringbuffer(dev);
        mutex_unlock(&dev->struct_mutex);
@@ -1539,14 +1477,11 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
        master->driver_priv = NULL;
 }
 
-static void i915_get_mem_freq(struct drm_device *dev)
+static void i915_pineview_get_mem_freq(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 tmp;
 
-       if (!IS_PINEVIEW(dev))
-               return;
-
        tmp = I915_READ(CLKCFG);
 
        switch (tmp & CLKCFG_FSB_MASK) {
@@ -1575,8 +1510,525 @@ static void i915_get_mem_freq(struct drm_device *dev)
                dev_priv->mem_freq = 800;
                break;
        }
+
+       /* detect pineview DDR3 setting */
+       tmp = I915_READ(CSHRDDR3CTL);
+       dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0;
+}
+
+static void i915_ironlake_get_mem_freq(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       u16 ddrpll, csipll;
+
+       ddrpll = I915_READ16(DDRMPLL1);
+       csipll = I915_READ16(CSIPLL0);
+
+       switch (ddrpll & 0xff) {
+       case 0xc:
+               dev_priv->mem_freq = 800;
+               break;
+       case 0x10:
+               dev_priv->mem_freq = 1066;
+               break;
+       case 0x14:
+               dev_priv->mem_freq = 1333;
+               break;
+       case 0x18:
+               dev_priv->mem_freq = 1600;
+               break;
+       default:
+               DRM_DEBUG_DRIVER("unknown memory frequency 0x%02x\n",
+                                ddrpll & 0xff);
+               dev_priv->mem_freq = 0;
+               break;
+       }
+
+       dev_priv->r_t = dev_priv->mem_freq;
+
+       switch (csipll & 0x3ff) {
+       case 0x00c:
+               dev_priv->fsb_freq = 3200;
+               break;
+       case 0x00e:
+               dev_priv->fsb_freq = 3733;
+               break;
+       case 0x010:
+               dev_priv->fsb_freq = 4266;
+               break;
+       case 0x012:
+               dev_priv->fsb_freq = 4800;
+               break;
+       case 0x014:
+               dev_priv->fsb_freq = 5333;
+               break;
+       case 0x016:
+               dev_priv->fsb_freq = 5866;
+               break;
+       case 0x018:
+               dev_priv->fsb_freq = 6400;
+               break;
+       default:
+               DRM_DEBUG_DRIVER("unknown fsb frequency 0x%04x\n",
+                                csipll & 0x3ff);
+               dev_priv->fsb_freq = 0;
+               break;
+       }
+
+       if (dev_priv->fsb_freq == 3200) {
+               dev_priv->c_m = 0;
+       } else if (dev_priv->fsb_freq > 3200 && dev_priv->fsb_freq <= 4800) {
+               dev_priv->c_m = 1;
+       } else {
+               dev_priv->c_m = 2;
+       }
+}
+
+struct v_table {
+       u8 vid;
+       unsigned long vd; /* in .1 mil */
+       unsigned long vm; /* in .1 mil */
+       u8 pvid;
+};
+
+static struct v_table v_table[] = {
+       { 0, 16125, 15000, 0x7f, },
+       { 1, 16000, 14875, 0x7e, },
+       { 2, 15875, 14750, 0x7d, },
+       { 3, 15750, 14625, 0x7c, },
+       { 4, 15625, 14500, 0x7b, },
+       { 5, 15500, 14375, 0x7a, },
+       { 6, 15375, 14250, 0x79, },
+       { 7, 15250, 14125, 0x78, },
+       { 8, 15125, 14000, 0x77, },
+       { 9, 15000, 13875, 0x76, },
+       { 10, 14875, 13750, 0x75, },
+       { 11, 14750, 13625, 0x74, },
+       { 12, 14625, 13500, 0x73, },
+       { 13, 14500, 13375, 0x72, },
+       { 14, 14375, 13250, 0x71, },
+       { 15, 14250, 13125, 0x70, },
+       { 16, 14125, 13000, 0x6f, },
+       { 17, 14000, 12875, 0x6e, },
+       { 18, 13875, 12750, 0x6d, },
+       { 19, 13750, 12625, 0x6c, },
+       { 20, 13625, 12500, 0x6b, },
+       { 21, 13500, 12375, 0x6a, },
+       { 22, 13375, 12250, 0x69, },
+       { 23, 13250, 12125, 0x68, },
+       { 24, 13125, 12000, 0x67, },
+       { 25, 13000, 11875, 0x66, },
+       { 26, 12875, 11750, 0x65, },
+       { 27, 12750, 11625, 0x64, },
+       { 28, 12625, 11500, 0x63, },
+       { 29, 12500, 11375, 0x62, },
+       { 30, 12375, 11250, 0x61, },
+       { 31, 12250, 11125, 0x60, },
+       { 32, 12125, 11000, 0x5f, },
+       { 33, 12000, 10875, 0x5e, },
+       { 34, 11875, 10750, 0x5d, },
+       { 35, 11750, 10625, 0x5c, },
+       { 36, 11625, 10500, 0x5b, },
+       { 37, 11500, 10375, 0x5a, },
+       { 38, 11375, 10250, 0x59, },
+       { 39, 11250, 10125, 0x58, },
+       { 40, 11125, 10000, 0x57, },
+       { 41, 11000, 9875, 0x56, },
+       { 42, 10875, 9750, 0x55, },
+       { 43, 10750, 9625, 0x54, },
+       { 44, 10625, 9500, 0x53, },
+       { 45, 10500, 9375, 0x52, },
+       { 46, 10375, 9250, 0x51, },
+       { 47, 10250, 9125, 0x50, },
+       { 48, 10125, 9000, 0x4f, },
+       { 49, 10000, 8875, 0x4e, },
+       { 50, 9875, 8750, 0x4d, },
+       { 51, 9750, 8625, 0x4c, },
+       { 52, 9625, 8500, 0x4b, },
+       { 53, 9500, 8375, 0x4a, },
+       { 54, 9375, 8250, 0x49, },
+       { 55, 9250, 8125, 0x48, },
+       { 56, 9125, 8000, 0x47, },
+       { 57, 9000, 7875, 0x46, },
+       { 58, 8875, 7750, 0x45, },
+       { 59, 8750, 7625, 0x44, },
+       { 60, 8625, 7500, 0x43, },
+       { 61, 8500, 7375, 0x42, },
+       { 62, 8375, 7250, 0x41, },
+       { 63, 8250, 7125, 0x40, },
+       { 64, 8125, 7000, 0x3f, },
+       { 65, 8000, 6875, 0x3e, },
+       { 66, 7875, 6750, 0x3d, },
+       { 67, 7750, 6625, 0x3c, },
+       { 68, 7625, 6500, 0x3b, },
+       { 69, 7500, 6375, 0x3a, },
+       { 70, 7375, 6250, 0x39, },
+       { 71, 7250, 6125, 0x38, },
+       { 72, 7125, 6000, 0x37, },
+       { 73, 7000, 5875, 0x36, },
+       { 74, 6875, 5750, 0x35, },
+       { 75, 6750, 5625, 0x34, },
+       { 76, 6625, 5500, 0x33, },
+       { 77, 6500, 5375, 0x32, },
+       { 78, 6375, 5250, 0x31, },
+       { 79, 6250, 5125, 0x30, },
+       { 80, 6125, 5000, 0x2f, },
+       { 81, 6000, 4875, 0x2e, },
+       { 82, 5875, 4750, 0x2d, },
+       { 83, 5750, 4625, 0x2c, },
+       { 84, 5625, 4500, 0x2b, },
+       { 85, 5500, 4375, 0x2a, },
+       { 86, 5375, 4250, 0x29, },
+       { 87, 5250, 4125, 0x28, },
+       { 88, 5125, 4000, 0x27, },
+       { 89, 5000, 3875, 0x26, },
+       { 90, 4875, 3750, 0x25, },
+       { 91, 4750, 3625, 0x24, },
+       { 92, 4625, 3500, 0x23, },
+       { 93, 4500, 3375, 0x22, },
+       { 94, 4375, 3250, 0x21, },
+       { 95, 4250, 3125, 0x20, },
+       { 96, 4125, 3000, 0x1f, },
+       { 97, 4125, 3000, 0x1e, },
+       { 98, 4125, 3000, 0x1d, },
+       { 99, 4125, 3000, 0x1c, },
+       { 100, 4125, 3000, 0x1b, },
+       { 101, 4125, 3000, 0x1a, },
+       { 102, 4125, 3000, 0x19, },
+       { 103, 4125, 3000, 0x18, },
+       { 104, 4125, 3000, 0x17, },
+       { 105, 4125, 3000, 0x16, },
+       { 106, 4125, 3000, 0x15, },
+       { 107, 4125, 3000, 0x14, },
+       { 108, 4125, 3000, 0x13, },
+       { 109, 4125, 3000, 0x12, },
+       { 110, 4125, 3000, 0x11, },
+       { 111, 4125, 3000, 0x10, },
+       { 112, 4125, 3000, 0x0f, },
+       { 113, 4125, 3000, 0x0e, },
+       { 114, 4125, 3000, 0x0d, },
+       { 115, 4125, 3000, 0x0c, },
+       { 116, 4125, 3000, 0x0b, },
+       { 117, 4125, 3000, 0x0a, },
+       { 118, 4125, 3000, 0x09, },
+       { 119, 4125, 3000, 0x08, },
+       { 120, 1125, 0, 0x07, },
+       { 121, 1000, 0, 0x06, },
+       { 122, 875, 0, 0x05, },
+       { 123, 750, 0, 0x04, },
+       { 124, 625, 0, 0x03, },
+       { 125, 500, 0, 0x02, },
+       { 126, 375, 0, 0x01, },
+       { 127, 0, 0, 0x00, },
+};
+
+struct cparams {
+       int i;
+       int t;
+       int m;
+       int c;
+};
+
+static struct cparams cparams[] = {
+       { 1, 1333, 301, 28664 },
+       { 1, 1066, 294, 24460 },
+       { 1, 800, 294, 25192 },
+       { 0, 1333, 276, 27605 },
+       { 0, 1066, 276, 27605 },
+       { 0, 800, 231, 23784 },
+};
+
+unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
+{
+       u64 total_count, diff, ret;
+       u32 count1, count2, count3, m = 0, c = 0;
+       unsigned long now = jiffies_to_msecs(jiffies), diff1;
+       int i;
+
+       diff1 = now - dev_priv->last_time1;
+
+       count1 = I915_READ(DMIEC);
+       count2 = I915_READ(DDREC);
+       count3 = I915_READ(CSIEC);
+
+       total_count = count1 + count2 + count3;
+
+       /* FIXME: handle per-counter overflow */
+       if (total_count < dev_priv->last_count1) {
+               diff = ~0UL - dev_priv->last_count1;
+               diff += total_count;
+       } else {
+               diff = total_count - dev_priv->last_count1;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(cparams); i++) {
+               if (cparams[i].i == dev_priv->c_m &&
+                   cparams[i].t == dev_priv->r_t) {
+                       m = cparams[i].m;
+                       c = cparams[i].c;
+                       break;
+               }
+       }
+
+       div_u64(diff, diff1);
+       ret = ((m * diff) + c);
+       div_u64(ret, 10);
+
+       dev_priv->last_count1 = total_count;
+       dev_priv->last_time1 = now;
+
+       return ret;
 }
 
+unsigned long i915_mch_val(struct drm_i915_private *dev_priv)
+{
+       unsigned long m, x, b;
+       u32 tsfs;
+
+       tsfs = I915_READ(TSFS);
+
+       m = ((tsfs & TSFS_SLOPE_MASK) >> TSFS_SLOPE_SHIFT);
+       x = I915_READ8(TR1);
+
+       b = tsfs & TSFS_INTR_MASK;
+
+       return ((m * x) / 127) - b;
+}
+
+static unsigned long pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
+{
+       unsigned long val = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(v_table); i++) {
+               if (v_table[i].pvid == pxvid) {
+                       if (IS_MOBILE(dev_priv->dev))
+                               val = v_table[i].vm;
+                       else
+                               val = v_table[i].vd;
+               }
+       }
+
+       return val;
+}
+
+void i915_update_gfx_val(struct drm_i915_private *dev_priv)
+{
+       struct timespec now, diff1;
+       u64 diff;
+       unsigned long diffms;
+       u32 count;
+
+       getrawmonotonic(&now);
+       diff1 = timespec_sub(now, dev_priv->last_time2);
+
+       /* Don't divide by 0 */
+       diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000;
+       if (!diffms)
+               return;
+
+       count = I915_READ(GFXEC);
+
+       if (count < dev_priv->last_count2) {
+               diff = ~0UL - dev_priv->last_count2;
+               diff += count;
+       } else {
+               diff = count - dev_priv->last_count2;
+       }
+
+       dev_priv->last_count2 = count;
+       dev_priv->last_time2 = now;
+
+       /* More magic constants... */
+       diff = diff * 1181;
+       div_u64(diff, diffms * 10);
+       dev_priv->gfx_power = diff;
+}
+
+unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
+{
+       unsigned long t, corr, state1, corr2, state2;
+       u32 pxvid, ext_v;
+
+       pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->cur_delay * 4));
+       pxvid = (pxvid >> 24) & 0x7f;
+       ext_v = pvid_to_extvid(dev_priv, pxvid);
+
+       state1 = ext_v;
+
+       t = i915_mch_val(dev_priv);
+
+       /* Revel in the empirically derived constants */
+
+       /* Correction factor in 1/100000 units */
+       if (t > 80)
+               corr = ((t * 2349) + 135940);
+       else if (t >= 50)
+               corr = ((t * 964) + 29317);
+       else /* < 50 */
+               corr = ((t * 301) + 1004);
+
+       corr = corr * ((150142 * state1) / 10000 - 78642);
+       corr /= 100000;
+       corr2 = (corr * dev_priv->corr);
+
+       state2 = (corr2 * state1) / 10000;
+       state2 /= 100; /* convert to mW */
+
+       i915_update_gfx_val(dev_priv);
+
+       return dev_priv->gfx_power + state2;
+}
+
+/* Global for IPS driver to get at the current i915 device */
+static struct drm_i915_private *i915_mch_dev;
+/*
+ * Lock protecting IPS related data structures
+ *   - i915_mch_dev
+ *   - dev_priv->max_delay
+ *   - dev_priv->min_delay
+ *   - dev_priv->fmax
+ *   - dev_priv->gpu_busy
+ */
+DEFINE_SPINLOCK(mchdev_lock);
+
+/**
+ * i915_read_mch_val - return value for IPS use
+ *
+ * Calculate and return a value for the IPS driver to use when deciding whether
+ * we have thermal and power headroom to increase CPU or GPU power budget.
+ */
+unsigned long i915_read_mch_val(void)
+{
+       struct drm_i915_private *dev_priv;
+       unsigned long chipset_val, graphics_val, ret = 0;
+
+       spin_lock(&mchdev_lock);
+       if (!i915_mch_dev)
+               goto out_unlock;
+       dev_priv = i915_mch_dev;
+
+       chipset_val = i915_chipset_val(dev_priv);
+       graphics_val = i915_gfx_val(dev_priv);
+
+       ret = chipset_val + graphics_val;
+
+out_unlock:
+       spin_unlock(&mchdev_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(i915_read_mch_val);
+
+/**
+ * i915_gpu_raise - raise GPU frequency limit
+ *
+ * Raise the limit; IPS indicates we have thermal headroom.
+ */
+bool i915_gpu_raise(void)
+{
+       struct drm_i915_private *dev_priv;
+       bool ret = true;
+
+       spin_lock(&mchdev_lock);
+       if (!i915_mch_dev) {
+               ret = false;
+               goto out_unlock;
+       }
+       dev_priv = i915_mch_dev;
+
+       if (dev_priv->max_delay > dev_priv->fmax)
+               dev_priv->max_delay--;
+
+out_unlock:
+       spin_unlock(&mchdev_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_raise);
+
+/**
+ * i915_gpu_lower - lower GPU frequency limit
+ *
+ * IPS indicates we're close to a thermal limit, so throttle back the GPU
+ * frequency maximum.
+ */
+bool i915_gpu_lower(void)
+{
+       struct drm_i915_private *dev_priv;
+       bool ret = true;
+
+       spin_lock(&mchdev_lock);
+       if (!i915_mch_dev) {
+               ret = false;
+               goto out_unlock;
+       }
+       dev_priv = i915_mch_dev;
+
+       if (dev_priv->max_delay < dev_priv->min_delay)
+               dev_priv->max_delay++;
+
+out_unlock:
+       spin_unlock(&mchdev_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_lower);
+
+/**
+ * i915_gpu_busy - indicate GPU business to IPS
+ *
+ * Tell the IPS driver whether or not the GPU is busy.
+ */
+bool i915_gpu_busy(void)
+{
+       struct drm_i915_private *dev_priv;
+       bool ret = false;
+
+       spin_lock(&mchdev_lock);
+       if (!i915_mch_dev)
+               goto out_unlock;
+       dev_priv = i915_mch_dev;
+
+       ret = dev_priv->busy;
+
+out_unlock:
+       spin_unlock(&mchdev_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_busy);
+
+/**
+ * i915_gpu_turbo_disable - disable graphics turbo
+ *
+ * Disable graphics turbo by resetting the max frequency and setting the
+ * current frequency to the default.
+ */
+bool i915_gpu_turbo_disable(void)
+{
+       struct drm_i915_private *dev_priv;
+       bool ret = true;
+
+       spin_lock(&mchdev_lock);
+       if (!i915_mch_dev) {
+               ret = false;
+               goto out_unlock;
+       }
+       dev_priv = i915_mch_dev;
+
+       dev_priv->max_delay = dev_priv->fstart;
+
+       if (!ironlake_set_drps(dev_priv->dev, dev_priv->fstart))
+               ret = false;
+
+out_unlock:
+       spin_unlock(&mchdev_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -1594,7 +2046,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        resource_size_t base, size;
        int ret = 0, mmio_bar;
        uint32_t agp_size, prealloc_size, prealloc_start;
-
        /* i915 has 4 more counters */
        dev->counters += 4;
        dev->types[6] = _DRM_STAT_IRQ;
@@ -1672,6 +2123,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                dev_priv->has_gem = 0;
        }
 
+       if (dev_priv->has_gem == 0 &&
+           drm_core_check_feature(dev, DRIVER_MODESET)) {
+               DRM_ERROR("kernel modesetting requires GEM, disabling driver.\n");
+               ret = -ENODEV;
+               goto out_iomapfree;
+       }
+
        dev->driver->get_vblank_counter = i915_get_vblank_counter;
        dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
        if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
@@ -1691,7 +2149,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                        goto out_workqueue_free;
        }
 
-       i915_get_mem_freq(dev);
+       if (IS_PINEVIEW(dev))
+               i915_pineview_get_mem_freq(dev);
+       else if (IS_IRONLAKE(dev))
+               i915_ironlake_get_mem_freq(dev);
 
        /* On the 945G/GM, the chipset reports the MSI capability on the
         * integrated graphics even though the support isn't actually there
@@ -1709,7 +2170,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        spin_lock_init(&dev_priv->user_irq_lock);
        spin_lock_init(&dev_priv->error_lock);
-       dev_priv->user_irq_refcount = 0;
        dev_priv->trace_irq_seqno = 0;
 
        ret = drm_vblank_init(dev, I915_NUM_PIPE);
@@ -1738,6 +2198,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
                    (unsigned long) dev);
+
+       spin_lock(&mchdev_lock);
+       i915_mch_dev = dev_priv;
+       dev_priv->mchdev_lock = &mchdev_lock;
+       spin_unlock(&mchdev_lock);
+
        return 0;
 
 out_workqueue_free:
@@ -1759,6 +2225,10 @@ int i915_driver_unload(struct drm_device *dev)
 
        i915_destroy_error_state(dev);
 
+       spin_lock(&mchdev_lock);
+       i915_mch_dev = NULL;
+       spin_unlock(&mchdev_lock);
+
        destroy_workqueue(dev_priv->wq);
        del_timer_sync(&dev_priv->hangcheck_timer);
 
index 5c51e45ab68de6e999946f4ea55d6c20ae24bc5c..423dc90c1e20589e7669f1ba41880308af9fb044 100644 (file)
@@ -60,95 +60,95 @@ extern int intel_agp_enabled;
        .subdevice = PCI_ANY_ID,                \
        .driver_data = (unsigned long) info }
 
-const static struct intel_device_info intel_i830_info = {
+static const struct intel_device_info intel_i830_info = {
        .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
 };
 
-const static struct intel_device_info intel_845g_info = {
+static const struct intel_device_info intel_845g_info = {
        .is_i8xx = 1,
 };
 
-const static struct intel_device_info intel_i85x_info = {
+static const struct intel_device_info intel_i85x_info = {
        .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1,
        .cursor_needs_physical = 1,
 };
 
-const static struct intel_device_info intel_i865g_info = {
+static const struct intel_device_info intel_i865g_info = {
        .is_i8xx = 1,
 };
 
-const static struct intel_device_info intel_i915g_info = {
+static const struct intel_device_info intel_i915g_info = {
        .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1,
 };
-const static struct intel_device_info intel_i915gm_info = {
+static const struct intel_device_info intel_i915gm_info = {
        .is_i9xx = 1,  .is_mobile = 1,
        .cursor_needs_physical = 1,
 };
-const static struct intel_device_info intel_i945g_info = {
+static const struct intel_device_info intel_i945g_info = {
        .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
 };
-const static struct intel_device_info intel_i945gm_info = {
+static const struct intel_device_info intel_i945gm_info = {
        .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1,
        .has_hotplug = 1, .cursor_needs_physical = 1,
 };
 
-const static struct intel_device_info intel_i965g_info = {
+static const struct intel_device_info intel_i965g_info = {
        .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1,
 };
 
-const static struct intel_device_info intel_i965gm_info = {
+static const struct intel_device_info intel_i965gm_info = {
        .is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1,
        .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1,
        .has_hotplug = 1,
 };
 
-const static struct intel_device_info intel_g33_info = {
+static const struct intel_device_info intel_g33_info = {
        .is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1,
        .has_hotplug = 1,
 };
 
-const static struct intel_device_info intel_g45_info = {
+static const struct intel_device_info intel_g45_info = {
        .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1,
        .has_pipe_cxsr = 1,
        .has_hotplug = 1,
 };
 
-const static struct intel_device_info intel_gm45_info = {
+static const struct intel_device_info intel_gm45_info = {
        .is_i965g = 1, .is_mobile = 1, .is_g4x = 1, .is_i9xx = 1,
        .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
        .has_pipe_cxsr = 1,
        .has_hotplug = 1,
 };
 
-const static struct intel_device_info intel_pineview_info = {
+static const struct intel_device_info intel_pineview_info = {
        .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
        .need_gfx_hws = 1,
        .has_hotplug = 1,
 };
 
-const static struct intel_device_info intel_ironlake_d_info = {
+static const struct intel_device_info intel_ironlake_d_info = {
        .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
        .has_pipe_cxsr = 1,
        .has_hotplug = 1,
 };
 
-const static struct intel_device_info intel_ironlake_m_info = {
+static const struct intel_device_info intel_ironlake_m_info = {
        .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
        .need_gfx_hws = 1, .has_rc6 = 1,
        .has_hotplug = 1,
 };
 
-const static struct intel_device_info intel_sandybridge_d_info = {
+static const struct intel_device_info intel_sandybridge_d_info = {
        .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
        .has_hotplug = 1, .is_gen6 = 1,
 };
 
-const static struct intel_device_info intel_sandybridge_m_info = {
+static const struct intel_device_info intel_sandybridge_m_info = {
        .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1,
        .has_hotplug = 1, .is_gen6 = 1,
 };
 
-const static struct pci_device_id pciidlist[] = {
+static const struct pci_device_id pciidlist[] = {
        INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
        INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
        INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
@@ -340,7 +340,7 @@ int i965_reset(struct drm_device *dev, u8 flags)
        /*
         * Clear request list
         */
-       i915_gem_retire_requests(dev);
+       i915_gem_retire_requests(dev, &dev_priv->render_ring);
 
        if (need_display)
                i915_save_display(dev);
@@ -370,6 +370,7 @@ int i965_reset(struct drm_device *dev, u8 flags)
                }
        } else {
                DRM_ERROR("Error occurred. Don't know how to reset this chip.\n");
+               mutex_unlock(&dev->struct_mutex);
                return -ENODEV;
        }
 
@@ -388,33 +389,10 @@ int i965_reset(struct drm_device *dev, u8 flags)
         * switched away).
         */
        if (drm_core_check_feature(dev, DRIVER_MODESET) ||
-           !dev_priv->mm.suspended) {
-               drm_i915_ring_buffer_t *ring = &dev_priv->ring;
-               struct drm_gem_object *obj = ring->ring_obj;
-               struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+                       !dev_priv->mm.suspended) {
+               struct intel_ring_buffer *ring = &dev_priv->render_ring;
                dev_priv->mm.suspended = 0;
-
-               /* Stop the ring if it's running. */
-               I915_WRITE(PRB0_CTL, 0);
-               I915_WRITE(PRB0_TAIL, 0);
-               I915_WRITE(PRB0_HEAD, 0);
-
-               /* Initialize the ring. */
-               I915_WRITE(PRB0_START, obj_priv->gtt_offset);
-               I915_WRITE(PRB0_CTL,
-                          ((obj->size - 4096) & RING_NR_PAGES) |
-                          RING_NO_REPORT |
-                          RING_VALID);
-               if (!drm_core_check_feature(dev, DRIVER_MODESET))
-                       i915_kernel_lost_context(dev);
-               else {
-                       ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-                       ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
-                       ring->space = ring->head - (ring->tail + 8);
-                       if (ring->space < 0)
-                               ring->space += ring->Size;
-               }
-
+               ring->init(dev, ring);
                mutex_unlock(&dev->struct_mutex);
                drm_irq_uninstall(dev);
                drm_irq_install(dev);
index 7f797ef1ab391f59ea181b6e6eb82c794aad1249..d147ab2f5bfcabfc8bc82cd5ccdea93064fa4cf0 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "i915_reg.h"
 #include "intel_bios.h"
+#include "intel_ringbuffer.h"
 #include <linux/io-mapping.h>
 
 /* General customization:
@@ -55,6 +56,8 @@ enum plane {
 
 #define I915_NUM_PIPE  2
 
+#define I915_GEM_GPU_DOMAINS   (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
+
 /* Interface history:
  *
  * 1.1: Original.
@@ -89,16 +92,6 @@ struct drm_i915_gem_phys_object {
        struct drm_gem_object *cur_obj;
 };
 
-typedef struct _drm_i915_ring_buffer {
-       unsigned long Size;
-       u8 *virtual_start;
-       int head;
-       int tail;
-       int space;
-       drm_local_map_t map;
-       struct drm_gem_object *ring_obj;
-} drm_i915_ring_buffer_t;
-
 struct mem_block {
        struct mem_block *next;
        struct mem_block *prev;
@@ -241,17 +234,15 @@ typedef struct drm_i915_private {
        void __iomem *regs;
 
        struct pci_dev *bridge_dev;
-       drm_i915_ring_buffer_t ring;
+       struct intel_ring_buffer render_ring;
+       struct intel_ring_buffer bsd_ring;
 
        drm_dma_handle_t *status_page_dmah;
-       void *hw_status_page;
        void *seqno_page;
        dma_addr_t dma_status_page;
        uint32_t counter;
-       unsigned int status_gfx_addr;
        unsigned int seqno_gfx_addr;
        drm_local_map_t hws_map;
-       struct drm_gem_object *hws_obj;
        struct drm_gem_object *seqno_obj;
        struct drm_gem_object *pwrctx;
 
@@ -267,8 +258,6 @@ typedef struct drm_i915_private {
        atomic_t irq_received;
        /** Protects user_irq_refcount and irq_mask_reg */
        spinlock_t user_irq_lock;
-       /** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */
-       int user_irq_refcount;
        u32 trace_irq_seqno;
        /** Cached value of IMR to avoid reads in updating the bitfield */
        u32 irq_mask_reg;
@@ -289,6 +278,7 @@ typedef struct drm_i915_private {
        struct mem_block *agp_heap;
        unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
        int vblank_pipe;
+       int num_pipe;
 
        /* For hangcheck timer */
 #define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */
@@ -334,7 +324,7 @@ typedef struct drm_i915_private {
        int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
        int num_fence_regs; /* 8 on pre-965, 16 otherwise */
 
-       unsigned int fsb_freq, mem_freq;
+       unsigned int fsb_freq, mem_freq, is_ddr3;
 
        spinlock_t error_lock;
        struct drm_i915_error_state *first_error;
@@ -514,18 +504,7 @@ typedef struct drm_i915_private {
                 */
                struct list_head shrink_list;
 
-               /**
-                * List of objects currently involved in rendering from the
-                * ringbuffer.
-                *
-                * Includes buffers having the contents of their GPU caches
-                * flushed, not necessarily primitives.  last_rendering_seqno
-                * represents when the rendering involved will be completed.
-                *
-                * A reference is held on the buffer while on this list.
-                */
                spinlock_t active_list_lock;
-               struct list_head active_list;
 
                /**
                 * List of objects which are not in the ringbuffer but which
@@ -562,12 +541,6 @@ typedef struct drm_i915_private {
                /** LRU list of objects with fence regs on them. */
                struct list_head fence_list;
 
-               /**
-                * List of breadcrumbs associated with GPU requests currently
-                * outstanding.
-                */
-               struct list_head request_list;
-
                /**
                 * We leave the user IRQ off as much as possible,
                 * but this means that requests will finish and never
@@ -623,6 +596,7 @@ typedef struct drm_i915_private {
        struct drm_crtc *plane_to_crtc_mapping[2];
        struct drm_crtc *pipe_to_crtc_mapping[2];
        wait_queue_head_t pending_flip_queue;
+       bool flip_pending_is_done;
 
        /* Reclocking support */
        bool render_reclock_avail;
@@ -644,6 +618,18 @@ typedef struct drm_i915_private {
        u8 cur_delay;
        u8 min_delay;
        u8 max_delay;
+       u8 fmax;
+       u8 fstart;
+
+       u64 last_count1;
+       unsigned long last_time1;
+       u64 last_count2;
+       struct timespec last_time2;
+       unsigned long gfx_power;
+       int c_m;
+       int r_t;
+       u8 corr;
+       spinlock_t *mchdev_lock;
 
        enum no_fbc_reason no_fbc_reason;
 
@@ -671,19 +657,64 @@ struct drm_i915_gem_object {
         * (has pending rendering), and is not set if it's on inactive (ready
         * to be unbound).
         */
-       int active;
+       unsigned int active : 1;
 
        /**
         * This is set if the object has been written to since last bound
         * to the GTT
         */
-       int dirty;
+       unsigned int dirty : 1;
+
+       /**
+        * Fence register bits (if any) for this object.  Will be set
+        * as needed when mapped into the GTT.
+        * Protected by dev->struct_mutex.
+        *
+        * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
+        */
+       int fence_reg : 5;
+
+       /**
+        * Used for checking the object doesn't appear more than once
+        * in an execbuffer object list.
+        */
+       unsigned int in_execbuffer : 1;
+
+       /**
+        * Advice: are the backing pages purgeable?
+        */
+       unsigned int madv : 2;
+
+       /**
+        * Refcount for the pages array. With the current locking scheme, there
+        * are at most two concurrent users: Binding a bo to the gtt and
+        * pwrite/pread using physical addresses. So two bits for a maximum
+        * of two users are enough.
+        */
+       unsigned int pages_refcount : 2;
+#define DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT 0x3
+
+       /**
+        * Current tiling mode for the object.
+        */
+       unsigned int tiling_mode : 2;
+
+       /** How many users have pinned this object in GTT space. The following
+        * users can each hold at most one reference: pwrite/pread, pin_ioctl
+        * (via user_pin_count), execbuffer (objects are not allowed multiple
+        * times for the same batchbuffer), and the framebuffer code. When
+        * switching/pageflipping, the framebuffer code has at most two buffers
+        * pinned per crtc.
+        *
+        * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
+        * bits with absolutely no headroom. So use 4 bits. */
+       int pin_count : 4;
+#define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
 
        /** AGP memory structure for our GTT binding. */
        DRM_AGP_MEM *agp_mem;
 
        struct page **pages;
-       int pages_refcount;
 
        /**
         * Current offset of the object in GTT space.
@@ -692,26 +723,18 @@ struct drm_i915_gem_object {
         */
        uint32_t gtt_offset;
 
+       /* Which ring is refering to is this object */
+       struct intel_ring_buffer *ring;
+
        /**
         * Fake offset for use by mmap(2)
         */
        uint64_t mmap_offset;
 
-       /**
-        * Fence register bits (if any) for this object.  Will be set
-        * as needed when mapped into the GTT.
-        * Protected by dev->struct_mutex.
-        */
-       int fence_reg;
-
-       /** How many users have pinned this object in GTT space */
-       int pin_count;
-
        /** Breadcrumb of last rendering to the buffer. */
        uint32_t last_rendering_seqno;
 
-       /** Current tiling mode for the object. */
-       uint32_t tiling_mode;
+       /** Current tiling stride for the object, if it's tiled. */
        uint32_t stride;
 
        /** Record of address bit 17 of each page at last unbind. */
@@ -733,17 +756,6 @@ struct drm_i915_gem_object {
        /** for phy allocated objects */
        struct drm_i915_gem_phys_object *phys_obj;
 
-       /**
-        * Used for checking the object doesn't appear more than once
-        * in an execbuffer object list.
-        */
-       int in_execbuffer;
-
-       /**
-        * Advice: are the backing pages purgeable?
-        */
-       int madv;
-
        /**
         * Number of crtcs where this object is currently the fb, but
         * will be page flipped away on the next vblank.  When it
@@ -765,6 +777,9 @@ struct drm_i915_gem_object {
  * an emission time with seqnos for tracking how far ahead of the GPU we are.
  */
 struct drm_i915_gem_request {
+       /** On Which ring this request was generated */
+       struct intel_ring_buffer *ring;
+
        /** GEM sequence number associated with this request. */
        uint32_t seqno;
 
@@ -821,6 +836,11 @@ extern int i915_emit_box(struct drm_device *dev,
                         struct drm_clip_rect *boxes,
                         int i, int DR1, int DR4);
 extern int i965_reset(struct drm_device *dev, u8 flags);
+extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
+extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
+extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
+extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
+
 
 /* i915_irq.c */
 void i915_hangcheck_elapsed(unsigned long data);
@@ -829,9 +849,7 @@ extern int i915_irq_emit(struct drm_device *dev, void *data,
                         struct drm_file *file_priv);
 extern int i915_irq_wait(struct drm_device *dev, void *data,
                         struct drm_file *file_priv);
-void i915_user_irq_get(struct drm_device *dev);
 void i915_trace_irq_get(struct drm_device *dev, u32 seqno);
-void i915_user_irq_put(struct drm_device *dev);
 extern void i915_enable_interrupt (struct drm_device *dev);
 
 extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
@@ -849,6 +867,11 @@ extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int i915_vblank_swap(struct drm_device *dev, void *data,
                            struct drm_file *file_priv);
 extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
+extern void i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask);
+extern void ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv,
+               u32 mask);
+extern void ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv,
+               u32 mask);
 
 void
 i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
@@ -922,11 +945,13 @@ void i915_gem_object_unpin(struct drm_gem_object *obj);
 int i915_gem_object_unbind(struct drm_gem_object *obj);
 void i915_gem_release_mmap(struct drm_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
-uint32_t i915_get_gem_seqno(struct drm_device *dev);
+uint32_t i915_get_gem_seqno(struct drm_device *dev,
+               struct intel_ring_buffer *ring);
 bool i915_seqno_passed(uint32_t seq1, uint32_t seq2);
 int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
 int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
-void i915_gem_retire_requests(struct drm_device *dev);
+void i915_gem_retire_requests(struct drm_device *dev,
+                struct intel_ring_buffer *ring);
 void i915_gem_retire_work_handler(struct work_struct *work);
 void i915_gem_clflush_object(struct drm_gem_object *obj);
 int i915_gem_object_set_domain(struct drm_gem_object *obj,
@@ -937,9 +962,13 @@ void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 int i915_gem_do_init(struct drm_device *dev, unsigned long start,
                     unsigned long end);
 int i915_gem_idle(struct drm_device *dev);
-uint32_t i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
-                         uint32_t flush_domains);
-int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible);
+uint32_t i915_add_request(struct drm_device *dev,
+               struct drm_file *file_priv,
+               uint32_t flush_domains,
+               struct intel_ring_buffer *ring);
+int i915_do_wait_request(struct drm_device *dev,
+               uint32_t seqno, int interruptible,
+               struct intel_ring_buffer *ring);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
                                      int write);
@@ -1015,7 +1044,7 @@ extern void g4x_disable_fbc(struct drm_device *dev);
 extern void intel_disable_fbc(struct drm_device *dev);
 extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
 extern bool intel_fbc_enabled(struct drm_device *dev);
-
+extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
 extern void intel_detect_pch (struct drm_device *dev);
 extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
 
@@ -1026,7 +1055,8 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
  * has access to the ring.
  */
 #define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do {                        \
-       if (((drm_i915_private_t *)dev->dev_private)->ring.ring_obj == NULL) \
+       if (((drm_i915_private_t *)dev->dev_private)->render_ring.gem_object \
+                       == NULL)                                        \
                LOCK_TEST_WITH_RETURN(dev, file_priv);                  \
 } while (0)
 
@@ -1039,35 +1069,31 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
 #define I915_WRITE64(reg, val) writeq(val, dev_priv->regs + (reg))
 #define I915_READ64(reg)       readq(dev_priv->regs + (reg))
 #define POSTING_READ(reg)      (void)I915_READ(reg)
+#define POSTING_READ16(reg)    (void)I915_READ16(reg)
 
 #define I915_VERBOSE 0
 
-#define RING_LOCALS    volatile unsigned int *ring_virt__;
-
-#define BEGIN_LP_RING(n) do {                                          \
-       int bytes__ = 4*(n);                                            \
-       if (I915_VERBOSE) DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n));        \
-       /* a wrap must occur between instructions so pad beforehand */  \
-       if (unlikely (dev_priv->ring.tail + bytes__ > dev_priv->ring.Size)) \
-               i915_wrap_ring(dev);                                    \
-       if (unlikely (dev_priv->ring.space < bytes__))                  \
-               i915_wait_ring(dev, bytes__, __func__);                 \
-       ring_virt__ = (unsigned int *)                                  \
-               (dev_priv->ring.virtual_start + dev_priv->ring.tail);   \
-       dev_priv->ring.tail += bytes__;                                 \
-       dev_priv->ring.tail &= dev_priv->ring.Size - 1;                 \
-       dev_priv->ring.space -= bytes__;                                \
+#define BEGIN_LP_RING(n)  do { \
+       drm_i915_private_t *dev_priv = dev->dev_private;                \
+       if (I915_VERBOSE)                                               \
+               DRM_DEBUG("   BEGIN_LP_RING %x\n", (int)(n));           \
+       intel_ring_begin(dev, &dev_priv->render_ring, (n));             \
 } while (0)
 
-#define OUT_RING(n) do {                                               \
-       if (I915_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));      \
-       *ring_virt__++ = (n);                                           \
+
+#define OUT_RING(x) do {                                               \
+       drm_i915_private_t *dev_priv = dev->dev_private;                \
+       if (I915_VERBOSE)                                               \
+               DRM_DEBUG("   OUT_RING %x\n", (int)(x));                \
+       intel_ring_emit(dev, &dev_priv->render_ring, x);                \
 } while (0)
 
 #define ADVANCE_LP_RING() do {                                         \
+       drm_i915_private_t *dev_priv = dev->dev_private;                \
        if (I915_VERBOSE)                                               \
-               DRM_DEBUG("ADVANCE_LP_RING %x\n", dev_priv->ring.tail); \
-       I915_WRITE(PRB0_TAIL, dev_priv->ring.tail);                     \
+               DRM_DEBUG("ADVANCE_LP_RING %x\n",                       \
+                               dev_priv->render_ring.tail);            \
+       intel_ring_advance(dev, &dev_priv->render_ring);                \
 } while(0)
 
 /**
@@ -1085,14 +1111,12 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
  *
  * The area from dword 0x20 to 0x3ff is available for driver usage.
  */
-#define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
+#define READ_HWSP(dev_priv, reg)  (((volatile u32 *)\
+                       (dev_priv->render_ring.status_page.page_addr))[reg])
 #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
 #define I915_GEM_HWS_INDEX             0x20
 #define I915_BREADCRUMB_INDEX          0x21
 
-extern int i915_wrap_ring(struct drm_device * dev);
-extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
-
 #define INTEL_INFO(dev)        (((struct drm_i915_private *) (dev)->dev_private)->info)
 
 #define IS_I830(dev)           ((dev)->pci_device == 0x3577)
@@ -1138,6 +1162,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
                         (dev)->pci_device == 0x2A42 ||         \
                         (dev)->pci_device == 0x2E42)
 
+#define HAS_BSD(dev)            (IS_IRONLAKE(dev) || IS_G4X(dev))
 #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
 
 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
index 112699f71fa4f5f0afdb4b2d03b4960243350d48..074385882ccfe721ff5630b9e825950c6479af7e 100644 (file)
@@ -35,8 +35,6 @@
 #include <linux/swap.h>
 #include <linux/pci.h>
 
-#define I915_GEM_GPU_DOMAINS   (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
-
 static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
 static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
 static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
@@ -169,7 +167,7 @@ static int i915_gem_object_needs_bit17_swizzle(struct drm_gem_object *obj)
                obj_priv->tiling_mode != I915_TILING_NONE;
 }
 
-static inline int
+static inline void
 slow_shmem_copy(struct page *dst_page,
                int dst_offset,
                struct page *src_page,
@@ -178,25 +176,16 @@ slow_shmem_copy(struct page *dst_page,
 {
        char *dst_vaddr, *src_vaddr;
 
-       dst_vaddr = kmap_atomic(dst_page, KM_USER0);
-       if (dst_vaddr == NULL)
-               return -ENOMEM;
-
-       src_vaddr = kmap_atomic(src_page, KM_USER1);
-       if (src_vaddr == NULL) {
-               kunmap_atomic(dst_vaddr, KM_USER0);
-               return -ENOMEM;
-       }
+       dst_vaddr = kmap(dst_page);
+       src_vaddr = kmap(src_page);
 
        memcpy(dst_vaddr + dst_offset, src_vaddr + src_offset, length);
 
-       kunmap_atomic(src_vaddr, KM_USER1);
-       kunmap_atomic(dst_vaddr, KM_USER0);
-
-       return 0;
+       kunmap(src_page);
+       kunmap(dst_page);
 }
 
-static inline int
+static inline void
 slow_shmem_bit17_copy(struct page *gpu_page,
                      int gpu_offset,
                      struct page *cpu_page,
@@ -216,15 +205,8 @@ slow_shmem_bit17_copy(struct page *gpu_page,
                                               cpu_page, cpu_offset, length);
        }
 
-       gpu_vaddr = kmap_atomic(gpu_page, KM_USER0);
-       if (gpu_vaddr == NULL)
-               return -ENOMEM;
-
-       cpu_vaddr = kmap_atomic(cpu_page, KM_USER1);
-       if (cpu_vaddr == NULL) {
-               kunmap_atomic(gpu_vaddr, KM_USER0);
-               return -ENOMEM;
-       }
+       gpu_vaddr = kmap(gpu_page);
+       cpu_vaddr = kmap(cpu_page);
 
        /* Copy the data, XORing A6 with A17 (1). The user already knows he's
         * XORing with the other bits (A9 for Y, A9 and A10 for X)
@@ -248,10 +230,8 @@ slow_shmem_bit17_copy(struct page *gpu_page,
                length -= this_length;
        }
 
-       kunmap_atomic(cpu_vaddr, KM_USER1);
-       kunmap_atomic(gpu_vaddr, KM_USER0);
-
-       return 0;
+       kunmap(cpu_page);
+       kunmap(gpu_page);
 }
 
 /**
@@ -427,21 +407,19 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
                        page_length = PAGE_SIZE - data_page_offset;
 
                if (do_bit17_swizzling) {
-                       ret = slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
-                                                   shmem_page_offset,
-                                                   user_pages[data_page_index],
-                                                   data_page_offset,
-                                                   page_length,
-                                                   1);
-               } else {
-                       ret = slow_shmem_copy(user_pages[data_page_index],
-                                             data_page_offset,
-                                             obj_priv->pages[shmem_page_index],
+                       slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
                                              shmem_page_offset,
-                                             page_length);
+                                             user_pages[data_page_index],
+                                             data_page_offset,
+                                             page_length,
+                                             1);
+               } else {
+                       slow_shmem_copy(user_pages[data_page_index],
+                                       data_page_offset,
+                                       obj_priv->pages[shmem_page_index],
+                                       shmem_page_offset,
+                                       page_length);
                }
-               if (ret)
-                       goto fail_put_pages;
 
                remain -= page_length;
                data_ptr += page_length;
@@ -531,25 +509,24 @@ fast_user_write(struct io_mapping *mapping,
  * page faults
  */
 
-static inline int
+static inline void
 slow_kernel_write(struct io_mapping *mapping,
                  loff_t gtt_base, int gtt_offset,
                  struct page *user_page, int user_offset,
                  int length)
 {
-       char *src_vaddr, *dst_vaddr;
-       unsigned long unwritten;
+       char __iomem *dst_vaddr;
+       char *src_vaddr;
 
-       dst_vaddr = io_mapping_map_atomic_wc(mapping, gtt_base);
-       src_vaddr = kmap_atomic(user_page, KM_USER1);
-       unwritten = __copy_from_user_inatomic_nocache(dst_vaddr + gtt_offset,
-                                                     src_vaddr + user_offset,
-                                                     length);
-       kunmap_atomic(src_vaddr, KM_USER1);
-       io_mapping_unmap_atomic(dst_vaddr);
-       if (unwritten)
-               return -EFAULT;
-       return 0;
+       dst_vaddr = io_mapping_map_wc(mapping, gtt_base);
+       src_vaddr = kmap(user_page);
+
+       memcpy_toio(dst_vaddr + gtt_offset,
+                   src_vaddr + user_offset,
+                   length);
+
+       kunmap(user_page);
+       io_mapping_unmap(dst_vaddr);
 }
 
 static inline int
@@ -722,18 +699,11 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
                if ((data_page_offset + page_length) > PAGE_SIZE)
                        page_length = PAGE_SIZE - data_page_offset;
 
-               ret = slow_kernel_write(dev_priv->mm.gtt_mapping,
-                                       gtt_page_base, gtt_page_offset,
-                                       user_pages[data_page_index],
-                                       data_page_offset,
-                                       page_length);
-
-               /* If we get a fault while copying data, then (presumably) our
-                * source page isn't available.  Return the error and we'll
-                * retry in the slow path.
-                */
-               if (ret)
-                       goto out_unpin_object;
+               slow_kernel_write(dev_priv->mm.gtt_mapping,
+                                 gtt_page_base, gtt_page_offset,
+                                 user_pages[data_page_index],
+                                 data_page_offset,
+                                 page_length);
 
                remain -= page_length;
                offset += page_length;
@@ -902,21 +872,19 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
                        page_length = PAGE_SIZE - data_page_offset;
 
                if (do_bit17_swizzling) {
-                       ret = slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
-                                                   shmem_page_offset,
-                                                   user_pages[data_page_index],
-                                                   data_page_offset,
-                                                   page_length,
-                                                   0);
-               } else {
-                       ret = slow_shmem_copy(obj_priv->pages[shmem_page_index],
+                       slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
                                              shmem_page_offset,
                                              user_pages[data_page_index],
                                              data_page_offset,
-                                             page_length);
+                                             page_length,
+                                             0);
+               } else {
+                       slow_shmem_copy(obj_priv->pages[shmem_page_index],
+                                       shmem_page_offset,
+                                       user_pages[data_page_index],
+                                       data_page_offset,
+                                       page_length);
                }
-               if (ret)
-                       goto fail_put_pages;
 
                remain -= page_length;
                data_ptr += page_length;
@@ -973,7 +941,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
        if (obj_priv->phys_obj)
                ret = i915_gem_phys_pwrite(dev, obj, args, file_priv);
        else if (obj_priv->tiling_mode == I915_TILING_NONE &&
-                dev->gtt_total != 0) {
+                dev->gtt_total != 0 &&
+                obj->write_domain != I915_GEM_DOMAIN_CPU) {
                ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file_priv);
                if (ret == -EFAULT) {
                        ret = i915_gem_gtt_pwrite_slow(dev, obj, args,
@@ -1484,11 +1453,14 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
 }
 
 static void
-i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno)
+i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno,
+                              struct intel_ring_buffer *ring)
 {
        struct drm_device *dev = obj->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+       BUG_ON(ring == NULL);
+       obj_priv->ring = ring;
 
        /* Add a reference if we're newly entering the active list. */
        if (!obj_priv->active) {
@@ -1497,8 +1469,7 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno)
        }
        /* Move from whatever list we were on to the tail of execution. */
        spin_lock(&dev_priv->mm.active_list_lock);
-       list_move_tail(&obj_priv->list,
-                      &dev_priv->mm.active_list);
+       list_move_tail(&obj_priv->list, &ring->active_list);
        spin_unlock(&dev_priv->mm.active_list_lock);
        obj_priv->last_rendering_seqno = seqno;
 }
@@ -1551,6 +1522,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
        BUG_ON(!list_empty(&obj_priv->gpu_write_list));
 
        obj_priv->last_rendering_seqno = 0;
+       obj_priv->ring = NULL;
        if (obj_priv->active) {
                obj_priv->active = 0;
                drm_gem_object_unreference(obj);
@@ -1560,7 +1532,8 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
 
 static void
 i915_gem_process_flushing_list(struct drm_device *dev,
-                              uint32_t flush_domains, uint32_t seqno)
+                              uint32_t flush_domains, uint32_t seqno,
+                              struct intel_ring_buffer *ring)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj_priv, *next;
@@ -1571,12 +1544,13 @@ i915_gem_process_flushing_list(struct drm_device *dev,
                struct drm_gem_object *obj = &obj_priv->base;
 
                if ((obj->write_domain & flush_domains) ==
-                   obj->write_domain) {
+                   obj->write_domain &&
+                   obj_priv->ring->ring_flag == ring->ring_flag) {
                        uint32_t old_write_domain = obj->write_domain;
 
                        obj->write_domain = 0;
                        list_del_init(&obj_priv->gpu_write_list);
-                       i915_gem_object_move_to_active(obj, seqno);
+                       i915_gem_object_move_to_active(obj, seqno, ring);
 
                        /* update the fence lru list */
                        if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
@@ -1593,31 +1567,15 @@ i915_gem_process_flushing_list(struct drm_device *dev,
        }
 }
 
-#define PIPE_CONTROL_FLUSH(addr)                                       \
-       OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |          \
-                PIPE_CONTROL_DEPTH_STALL);                             \
-       OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT);                       \
-       OUT_RING(0);                                                    \
-       OUT_RING(0);                                                    \
-
-/**
- * Creates a new sequence number, emitting a write of it to the status page
- * plus an interrupt, which will trigger i915_user_interrupt_handler.
- *
- * Must be called with struct_lock held.
- *
- * Returned sequence numbers are nonzero on success.
- */
 uint32_t
 i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
-                uint32_t flush_domains)
+                uint32_t flush_domains, struct intel_ring_buffer *ring)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_file_private *i915_file_priv = NULL;
        struct drm_i915_gem_request *request;
        uint32_t seqno;
        int was_empty;
-       RING_LOCALS;
 
        if (file_priv != NULL)
                i915_file_priv = file_priv->driver_priv;
@@ -1626,62 +1584,14 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
        if (request == NULL)
                return 0;
 
-       /* Grab the seqno we're going to make this request be, and bump the
-        * next (skipping 0 so it can be the reserved no-seqno value).
-        */
-       seqno = dev_priv->mm.next_gem_seqno;
-       dev_priv->mm.next_gem_seqno++;
-       if (dev_priv->mm.next_gem_seqno == 0)
-               dev_priv->mm.next_gem_seqno++;
-
-       if (HAS_PIPE_CONTROL(dev)) {
-               u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
-
-               /*
-                * Workaround qword write incoherence by flushing the
-                * PIPE_NOTIFY buffers out to memory before requesting
-                * an interrupt.
-                */
-               BEGIN_LP_RING(32);
-               OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-                        PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
-               OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
-               OUT_RING(seqno);
-               OUT_RING(0);
-               PIPE_CONTROL_FLUSH(scratch_addr);
-               scratch_addr += 128; /* write to separate cachelines */
-               PIPE_CONTROL_FLUSH(scratch_addr);
-               scratch_addr += 128;
-               PIPE_CONTROL_FLUSH(scratch_addr);
-               scratch_addr += 128;
-               PIPE_CONTROL_FLUSH(scratch_addr);
-               scratch_addr += 128;
-               PIPE_CONTROL_FLUSH(scratch_addr);
-               scratch_addr += 128;
-               PIPE_CONTROL_FLUSH(scratch_addr);
-               OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-                        PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
-                        PIPE_CONTROL_NOTIFY);
-               OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
-               OUT_RING(seqno);
-               OUT_RING(0);
-               ADVANCE_LP_RING();
-       } else {
-               BEGIN_LP_RING(4);
-               OUT_RING(MI_STORE_DWORD_INDEX);
-               OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-               OUT_RING(seqno);
-
-               OUT_RING(MI_USER_INTERRUPT);
-               ADVANCE_LP_RING();
-       }
-
-       DRM_DEBUG_DRIVER("%d\n", seqno);
+       seqno = ring->add_request(dev, ring, file_priv, flush_domains);
 
        request->seqno = seqno;
+       request->ring = ring;
        request->emitted_jiffies = jiffies;
-       was_empty = list_empty(&dev_priv->mm.request_list);
-       list_add_tail(&request->list, &dev_priv->mm.request_list);
+       was_empty = list_empty(&ring->request_list);
+       list_add_tail(&request->list, &ring->request_list);
+
        if (i915_file_priv) {
                list_add_tail(&request->client_list,
                              &i915_file_priv->mm.request_list);
@@ -1693,7 +1603,7 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
         * domain we're flushing with our flush.
         */
        if (flush_domains != 0) 
-               i915_gem_process_flushing_list(dev, flush_domains, seqno);
+               i915_gem_process_flushing_list(dev, flush_domains, seqno, ring);
 
        if (!dev_priv->mm.suspended) {
                mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
@@ -1710,20 +1620,16 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
  * before signalling the CPU
  */
 static uint32_t
-i915_retire_commands(struct drm_device *dev)
+i915_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       uint32_t cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
        uint32_t flush_domains = 0;
-       RING_LOCALS;
 
        /* The sampler always gets flushed on i965 (sigh) */
        if (IS_I965G(dev))
                flush_domains |= I915_GEM_DOMAIN_SAMPLER;
-       BEGIN_LP_RING(2);
-       OUT_RING(cmd);
-       OUT_RING(0); /* noop */
-       ADVANCE_LP_RING();
+
+       ring->flush(dev, ring,
+                       I915_GEM_DOMAIN_COMMAND, flush_domains);
        return flush_domains;
 }
 
@@ -1743,11 +1649,11 @@ i915_gem_retire_request(struct drm_device *dev,
         * by the ringbuffer to the flushing/inactive lists as appropriate.
         */
        spin_lock(&dev_priv->mm.active_list_lock);
-       while (!list_empty(&dev_priv->mm.active_list)) {
+       while (!list_empty(&request->ring->active_list)) {
                struct drm_gem_object *obj;
                struct drm_i915_gem_object *obj_priv;
 
-               obj_priv = list_first_entry(&dev_priv->mm.active_list,
+               obj_priv = list_first_entry(&request->ring->active_list,
                                            struct drm_i915_gem_object,
                                            list);
                obj = &obj_priv->base;
@@ -1794,35 +1700,33 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
 }
 
 uint32_t
-i915_get_gem_seqno(struct drm_device *dev)
+i915_get_gem_seqno(struct drm_device *dev,
+                  struct intel_ring_buffer *ring)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       if (HAS_PIPE_CONTROL(dev))
-               return ((volatile u32 *)(dev_priv->seqno_page))[0];
-       else
-               return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
+       return ring->get_gem_seqno(dev, ring);
 }
 
 /**
  * This function clears the request list as sequence numbers are passed.
  */
 void
-i915_gem_retire_requests(struct drm_device *dev)
+i915_gem_retire_requests(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        uint32_t seqno;
 
-       if (!dev_priv->hw_status_page || list_empty(&dev_priv->mm.request_list))
+       if (!ring->status_page.page_addr
+                       || list_empty(&ring->request_list))
                return;
 
-       seqno = i915_get_gem_seqno(dev);
+       seqno = i915_get_gem_seqno(dev, ring);
 
-       while (!list_empty(&dev_priv->mm.request_list)) {
+       while (!list_empty(&ring->request_list)) {
                struct drm_i915_gem_request *request;
                uint32_t retiring_seqno;
 
-               request = list_first_entry(&dev_priv->mm.request_list,
+               request = list_first_entry(&ring->request_list,
                                           struct drm_i915_gem_request,
                                           list);
                retiring_seqno = request->seqno;
@@ -1840,7 +1744,8 @@ i915_gem_retire_requests(struct drm_device *dev)
 
        if (unlikely (dev_priv->trace_irq_seqno &&
                      i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) {
-               i915_user_irq_put(dev);
+
+               ring->user_irq_put(dev, ring);
                dev_priv->trace_irq_seqno = 0;
        }
 }
@@ -1856,15 +1761,22 @@ i915_gem_retire_work_handler(struct work_struct *work)
        dev = dev_priv->dev;
 
        mutex_lock(&dev->struct_mutex);
-       i915_gem_retire_requests(dev);
+       i915_gem_retire_requests(dev, &dev_priv->render_ring);
+
+       if (HAS_BSD(dev))
+               i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
+
        if (!dev_priv->mm.suspended &&
-           !list_empty(&dev_priv->mm.request_list))
+               (!list_empty(&dev_priv->render_ring.request_list) ||
+                       (HAS_BSD(dev) &&
+                        !list_empty(&dev_priv->bsd_ring.request_list))))
                queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
        mutex_unlock(&dev->struct_mutex);
 }
 
 int
-i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
+i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
+               int interruptible, struct intel_ring_buffer *ring)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 ier;
@@ -1875,7 +1787,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
        if (atomic_read(&dev_priv->mm.wedged))
                return -EIO;
 
-       if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
+       if (!i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno)) {
                if (HAS_PCH_SPLIT(dev))
                        ier = I915_READ(DEIER) | I915_READ(GTIER);
                else
@@ -1889,19 +1801,21 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
 
                trace_i915_gem_request_wait_begin(dev, seqno);
 
-               dev_priv->mm.waiting_gem_seqno = seqno;
-               i915_user_irq_get(dev);
+               ring->waiting_gem_seqno = seqno;
+               ring->user_irq_get(dev, ring);
                if (interruptible)
-                       ret = wait_event_interruptible(dev_priv->irq_queue,
-                               i915_seqno_passed(i915_get_gem_seqno(dev), seqno) ||
-                               atomic_read(&dev_priv->mm.wedged));
+                       ret = wait_event_interruptible(ring->irq_queue,
+                               i915_seqno_passed(
+                                       ring->get_gem_seqno(dev, ring), seqno)
+                               || atomic_read(&dev_priv->mm.wedged));
                else
-                       wait_event(dev_priv->irq_queue,
-                               i915_seqno_passed(i915_get_gem_seqno(dev), seqno) ||
-                               atomic_read(&dev_priv->mm.wedged));
+                       wait_event(ring->irq_queue,
+                               i915_seqno_passed(
+                                       ring->get_gem_seqno(dev, ring), seqno)
+                               || atomic_read(&dev_priv->mm.wedged));
 
-               i915_user_irq_put(dev);
-               dev_priv->mm.waiting_gem_seqno = 0;
+               ring->user_irq_put(dev, ring);
+               ring->waiting_gem_seqno = 0;
 
                trace_i915_gem_request_wait_end(dev, seqno);
        }
@@ -1910,7 +1824,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
 
        if (ret && ret != -ERESTARTSYS)
                DRM_ERROR("%s returns %d (awaiting %d at %d)\n",
-                         __func__, ret, seqno, i915_get_gem_seqno(dev));
+                         __func__, ret, seqno, ring->get_gem_seqno(dev, ring));
 
        /* Directly dispatch request retiring.  While we have the work queue
         * to handle this, the waiter on a request often wants an associated
@@ -1918,7 +1832,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
         * a separate wait queue to handle that.
         */
        if (ret == 0)
-               i915_gem_retire_requests(dev);
+               i915_gem_retire_requests(dev, ring);
 
        return ret;
 }
@@ -1928,9 +1842,10 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
  * request and object lists appropriately for that event.
  */
 static int
-i915_wait_request(struct drm_device *dev, uint32_t seqno)
+i915_wait_request(struct drm_device *dev, uint32_t seqno,
+               struct intel_ring_buffer *ring)
 {
-       return i915_do_wait_request(dev, seqno, 1);
+       return i915_do_wait_request(dev, seqno, 1, ring);
 }
 
 static void
@@ -1939,71 +1854,29 @@ i915_gem_flush(struct drm_device *dev,
               uint32_t flush_domains)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       uint32_t cmd;
-       RING_LOCALS;
-
-#if WATCH_EXEC
-       DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
-                 invalidate_domains, flush_domains);
-#endif
-       trace_i915_gem_request_flush(dev, dev_priv->mm.next_gem_seqno,
-                                    invalidate_domains, flush_domains);
-
        if (flush_domains & I915_GEM_DOMAIN_CPU)
                drm_agp_chipset_flush(dev);
+       dev_priv->render_ring.flush(dev, &dev_priv->render_ring,
+                       invalidate_domains,
+                       flush_domains);
+
+       if (HAS_BSD(dev))
+               dev_priv->bsd_ring.flush(dev, &dev_priv->bsd_ring,
+                               invalidate_domains,
+                               flush_domains);
+}
 
-       if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) {
-               /*
-                * read/write caches:
-                *
-                * I915_GEM_DOMAIN_RENDER is always invalidated, but is
-                * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
-                * also flushed at 2d versus 3d pipeline switches.
-                *
-                * read-only caches:
-                *
-                * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
-                * MI_READ_FLUSH is set, and is always flushed on 965.
-                *
-                * I915_GEM_DOMAIN_COMMAND may not exist?
-                *
-                * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
-                * invalidated when MI_EXE_FLUSH is set.
-                *
-                * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
-                * invalidated with every MI_FLUSH.
-                *
-                * TLBs:
-                *
-                * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
-                * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
-                * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
-                * are flushed at any MI_FLUSH.
-                */
-
-               cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
-               if ((invalidate_domains|flush_domains) &
-                   I915_GEM_DOMAIN_RENDER)
-                       cmd &= ~MI_NO_WRITE_FLUSH;
-               if (!IS_I965G(dev)) {
-                       /*
-                        * On the 965, the sampler cache always gets flushed
-                        * and this bit is reserved.
-                        */
-                       if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
-                               cmd |= MI_READ_FLUSH;
-               }
-               if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
-                       cmd |= MI_EXE_FLUSH;
-
-#if WATCH_EXEC
-               DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
-#endif
-               BEGIN_LP_RING(2);
-               OUT_RING(cmd);
-               OUT_RING(MI_NOOP);
-               ADVANCE_LP_RING();
-       }
+static void
+i915_gem_flush_ring(struct drm_device *dev,
+              uint32_t invalidate_domains,
+              uint32_t flush_domains,
+              struct intel_ring_buffer *ring)
+{
+       if (flush_domains & I915_GEM_DOMAIN_CPU)
+               drm_agp_chipset_flush(dev);
+       ring->flush(dev, ring,
+                       invalidate_domains,
+                       flush_domains);
 }
 
 /**
@@ -2030,7 +1903,8 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj)
                DRM_INFO("%s: object %p wait for seqno %08x\n",
                          __func__, obj, obj_priv->last_rendering_seqno);
 #endif
-               ret = i915_wait_request(dev, obj_priv->last_rendering_seqno);
+               ret = i915_wait_request(dev,
+                               obj_priv->last_rendering_seqno, obj_priv->ring);
                if (ret != 0)
                        return ret;
        }
@@ -2146,11 +2020,14 @@ i915_gpu_idle(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        bool lists_empty;
-       uint32_t seqno;
+       uint32_t seqno1, seqno2;
+       int ret;
 
        spin_lock(&dev_priv->mm.active_list_lock);
-       lists_empty = list_empty(&dev_priv->mm.flushing_list) &&
-                     list_empty(&dev_priv->mm.active_list);
+       lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
+                      list_empty(&dev_priv->render_ring.active_list) &&
+                      (!HAS_BSD(dev) ||
+                       list_empty(&dev_priv->bsd_ring.active_list)));
        spin_unlock(&dev_priv->mm.active_list_lock);
 
        if (lists_empty)
@@ -2158,11 +2035,25 @@ i915_gpu_idle(struct drm_device *dev)
 
        /* Flush everything onto the inactive list. */
        i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
-       seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
-       if (seqno == 0)
+       seqno1 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS,
+                       &dev_priv->render_ring);
+       if (seqno1 == 0)
                return -ENOMEM;
+       ret = i915_wait_request(dev, seqno1, &dev_priv->render_ring);
+
+       if (HAS_BSD(dev)) {
+               seqno2 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS,
+                               &dev_priv->bsd_ring);
+               if (seqno2 == 0)
+                       return -ENOMEM;
+
+               ret = i915_wait_request(dev, seqno2, &dev_priv->bsd_ring);
+               if (ret)
+                       return ret;
+       }
+
 
-       return i915_wait_request(dev, seqno);
+       return ret;
 }
 
 static int
@@ -2175,7 +2066,9 @@ i915_gem_evict_everything(struct drm_device *dev)
        spin_lock(&dev_priv->mm.active_list_lock);
        lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
                       list_empty(&dev_priv->mm.flushing_list) &&
-                      list_empty(&dev_priv->mm.active_list));
+                      list_empty(&dev_priv->render_ring.active_list) &&
+                      (!HAS_BSD(dev)
+                       || list_empty(&dev_priv->bsd_ring.active_list)));
        spin_unlock(&dev_priv->mm.active_list_lock);
 
        if (lists_empty)
@@ -2195,7 +2088,9 @@ i915_gem_evict_everything(struct drm_device *dev)
        spin_lock(&dev_priv->mm.active_list_lock);
        lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
                       list_empty(&dev_priv->mm.flushing_list) &&
-                      list_empty(&dev_priv->mm.active_list));
+                      list_empty(&dev_priv->render_ring.active_list) &&
+                      (!HAS_BSD(dev)
+                       || list_empty(&dev_priv->bsd_ring.active_list)));
        spin_unlock(&dev_priv->mm.active_list_lock);
        BUG_ON(!lists_empty);
 
@@ -2209,8 +2104,13 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
        struct drm_gem_object *obj;
        int ret;
 
+       struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
+       struct intel_ring_buffer *bsd_ring = &dev_priv->bsd_ring;
        for (;;) {
-               i915_gem_retire_requests(dev);
+               i915_gem_retire_requests(dev, render_ring);
+
+               if (HAS_BSD(dev))
+                       i915_gem_retire_requests(dev, bsd_ring);
 
                /* If there's an inactive buffer available now, grab it
                 * and be done.
@@ -2234,14 +2134,30 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
                 * things, wait for the next to finish and hopefully leave us
                 * a buffer to evict.
                 */
-               if (!list_empty(&dev_priv->mm.request_list)) {
+               if (!list_empty(&render_ring->request_list)) {
+                       struct drm_i915_gem_request *request;
+
+                       request = list_first_entry(&render_ring->request_list,
+                                                  struct drm_i915_gem_request,
+                                                  list);
+
+                       ret = i915_wait_request(dev,
+                                       request->seqno, request->ring);
+                       if (ret)
+                               return ret;
+
+                       continue;
+               }
+
+               if (HAS_BSD(dev) && !list_empty(&bsd_ring->request_list)) {
                        struct drm_i915_gem_request *request;
 
-                       request = list_first_entry(&dev_priv->mm.request_list,
+                       request = list_first_entry(&bsd_ring->request_list,
                                                   struct drm_i915_gem_request,
                                                   list);
 
-                       ret = i915_wait_request(dev, request->seqno);
+                       ret = i915_wait_request(dev,
+                                       request->seqno, request->ring);
                        if (ret)
                                return ret;
 
@@ -2268,10 +2184,13 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
                        if (obj != NULL) {
                                uint32_t seqno;
 
-                               i915_gem_flush(dev,
+                               i915_gem_flush_ring(dev,
+                                              obj->write_domain,
                                               obj->write_domain,
-                                              obj->write_domain);
-                               seqno = i915_add_request(dev, NULL, obj->write_domain);
+                                              obj_priv->ring);
+                               seqno = i915_add_request(dev, NULL,
+                                               obj->write_domain,
+                                               obj_priv->ring);
                                if (seqno == 0)
                                        return -ENOMEM;
                                continue;
@@ -2299,6 +2218,9 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
        struct inode *inode;
        struct page *page;
 
+       BUG_ON(obj_priv->pages_refcount
+                       == DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT);
+
        if (obj_priv->pages_refcount++ != 0)
                return 0;
 
@@ -2317,7 +2239,7 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
        mapping = inode->i_mapping;
        for (i = 0; i < page_count; i++) {
                page = read_cache_page_gfp(mapping, i,
-                                          mapping_gfp_mask (mapping) |
+                                          GFP_HIGHUSER |
                                           __GFP_COLD |
                                           gfpmask);
                if (IS_ERR(page))
@@ -2697,6 +2619,14 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
                return -EINVAL;
        }
 
+       /* If the object is bigger than the entire aperture, reject it early
+        * before evicting everything in a vain attempt to find space.
+        */
+       if (obj->size > dev->gtt_total) {
+               DRM_ERROR("Attempting to bind an object larger than the aperture\n");
+               return -E2BIG;
+       }
+
  search_free:
        free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
                                        obj->size, alignment, 0);
@@ -2807,6 +2737,7 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
        uint32_t old_write_domain;
+       struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 
        if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
                return;
@@ -2814,7 +2745,7 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
        /* Queue the GPU write cache flushing we need. */
        old_write_domain = obj->write_domain;
        i915_gem_flush(dev, 0, obj->write_domain);
-       (void) i915_add_request(dev, NULL, obj->write_domain);
+       (void) i915_add_request(dev, NULL, obj->write_domain, obj_priv->ring);
        BUG_ON(obj->write_domain);
 
        trace_i915_gem_object_change_domain(obj,
@@ -2954,23 +2885,24 @@ i915_gem_object_set_to_display_plane(struct drm_gem_object *obj)
                DRM_INFO("%s: object %p wait for seqno %08x\n",
                          __func__, obj, obj_priv->last_rendering_seqno);
 #endif
-               ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0);
+               ret = i915_do_wait_request(dev,
+                               obj_priv->last_rendering_seqno,
+                               0,
+                               obj_priv->ring);
                if (ret != 0)
                        return ret;
        }
 
+       i915_gem_object_flush_cpu_write_domain(obj);
+
        old_write_domain = obj->write_domain;
        old_read_domains = obj->read_domains;
 
-       obj->read_domains &= I915_GEM_DOMAIN_GTT;
-
-       i915_gem_object_flush_cpu_write_domain(obj);
-
        /* It should now be out of any other write domains, and we can update
         * the domain values for our changes.
         */
        BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
-       obj->read_domains |= I915_GEM_DOMAIN_GTT;
+       obj->read_domains = I915_GEM_DOMAIN_GTT;
        obj->write_domain = I915_GEM_DOMAIN_GTT;
        obj_priv->dirty = 1;
 
@@ -3354,9 +3286,13 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                     obj_priv->tiling_mode != I915_TILING_NONE;
 
        /* Check fence reg constraints and rebind if necessary */
-       if (need_fence && !i915_gem_object_fence_offset_ok(obj,
-           obj_priv->tiling_mode))
-               i915_gem_object_unbind(obj);
+       if (need_fence &&
+           !i915_gem_object_fence_offset_ok(obj,
+                                            obj_priv->tiling_mode)) {
+               ret = i915_gem_object_unbind(obj);
+               if (ret)
+                       return ret;
+       }
 
        /* Choose the GTT offset for our buffer and put it there. */
        ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
@@ -3370,9 +3306,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
        if (need_fence) {
                ret = i915_gem_object_get_fence_reg(obj);
                if (ret != 0) {
-                       if (ret != -EBUSY && ret != -ERESTARTSYS)
-                               DRM_ERROR("Failure to install fence: %d\n",
-                                         ret);
                        i915_gem_object_unpin(obj);
                        return ret;
                }
@@ -3545,62 +3478,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
        return 0;
 }
 
-/** Dispatch a batchbuffer to the ring
- */
-static int
-i915_dispatch_gem_execbuffer(struct drm_device *dev,
-                             struct drm_i915_gem_execbuffer2 *exec,
-                             struct drm_clip_rect *cliprects,
-                             uint64_t exec_offset)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       int nbox = exec->num_cliprects;
-       int i = 0, count;
-       uint32_t exec_start, exec_len;
-       RING_LOCALS;
-
-       exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
-       exec_len = (uint32_t) exec->batch_len;
-
-       trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1);
-
-       count = nbox ? nbox : 1;
-
-       for (i = 0; i < count; i++) {
-               if (i < nbox) {
-                       int ret = i915_emit_box(dev, cliprects, i,
-                                               exec->DR1, exec->DR4);
-                       if (ret)
-                               return ret;
-               }
-
-               if (IS_I830(dev) || IS_845G(dev)) {
-                       BEGIN_LP_RING(4);
-                       OUT_RING(MI_BATCH_BUFFER);
-                       OUT_RING(exec_start | MI_BATCH_NON_SECURE);
-                       OUT_RING(exec_start + exec_len - 4);
-                       OUT_RING(0);
-                       ADVANCE_LP_RING();
-               } else {
-                       BEGIN_LP_RING(2);
-                       if (IS_I965G(dev)) {
-                               OUT_RING(MI_BATCH_BUFFER_START |
-                                        (2 << 6) |
-                                        MI_BATCH_NON_SECURE_I965);
-                               OUT_RING(exec_start);
-                       } else {
-                               OUT_RING(MI_BATCH_BUFFER_START |
-                                        (2 << 6));
-                               OUT_RING(exec_start | MI_BATCH_NON_SECURE);
-                       }
-                       ADVANCE_LP_RING();
-               }
-       }
-
-       /* XXX breadcrumb */
-       return 0;
-}
-
 /* Throttle our rendering by waiting until the ring has completed our requests
  * emitted over 20 msec ago.
  *
@@ -3629,7 +3506,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv)
                if (time_after_eq(request->emitted_jiffies, recent_enough))
                        break;
 
-               ret = i915_wait_request(dev, request->seqno);
+               ret = i915_wait_request(dev, request->seqno, request->ring);
                if (ret != 0)
                        break;
        }
@@ -3786,10 +3663,22 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        uint32_t seqno, flush_domains, reloc_index;
        int pin_tries, flips;
 
+       struct intel_ring_buffer *ring = NULL;
+
 #if WATCH_EXEC
        DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
                  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
 #endif
+       if (args->flags & I915_EXEC_BSD) {
+               if (!HAS_BSD(dev)) {
+                       DRM_ERROR("execbuf with wrong flag\n");
+                       return -EINVAL;
+               }
+               ring = &dev_priv->bsd_ring;
+       } else {
+               ring = &dev_priv->render_ring;
+       }
+
 
        if (args->buffer_count < 1) {
                DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
@@ -3902,11 +3791,19 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                if (ret != -ENOSPC || pin_tries >= 1) {
                        if (ret != -ERESTARTSYS) {
                                unsigned long long total_size = 0;
-                               for (i = 0; i < args->buffer_count; i++)
+                               int num_fences = 0;
+                               for (i = 0; i < args->buffer_count; i++) {
+                                       obj_priv = object_list[i]->driver_private;
+
                                        total_size += object_list[i]->size;
-                               DRM_ERROR("Failed to pin buffer %d of %d, total %llu bytes: %d\n",
+                                       num_fences +=
+                                               exec_list[i].flags & EXEC_OBJECT_NEEDS_FENCE &&
+                                               obj_priv->tiling_mode != I915_TILING_NONE;
+                               }
+                               DRM_ERROR("Failed to pin buffer %d of %d, total %llu bytes, %d fences: %d\n",
                                          pinned+1, args->buffer_count,
-                                         total_size, ret);
+                                         total_size, num_fences,
+                                         ret);
                                DRM_ERROR("%d objects [%d pinned], "
                                          "%d object bytes [%d pinned], "
                                          "%d/%d gtt bytes\n",
@@ -3976,9 +3873,16 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                i915_gem_flush(dev,
                               dev->invalidate_domains,
                               dev->flush_domains);
-               if (dev->flush_domains & I915_GEM_GPU_DOMAINS)
+               if (dev->flush_domains & I915_GEM_GPU_DOMAINS) {
                        (void)i915_add_request(dev, file_priv,
-                                              dev->flush_domains);
+                                       dev->flush_domains,
+                                       &dev_priv->render_ring);
+
+                       if (HAS_BSD(dev))
+                               (void)i915_add_request(dev, file_priv,
+                                               dev->flush_domains,
+                                               &dev_priv->bsd_ring);
+               }
        }
 
        for (i = 0; i < args->buffer_count; i++) {
@@ -4015,7 +3919,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 #endif
 
        /* Exec the batchbuffer */
-       ret = i915_dispatch_gem_execbuffer(dev, args, cliprects, exec_offset);
+       ret = ring->dispatch_gem_execbuffer(dev, ring, args,
+                       cliprects, exec_offset);
        if (ret) {
                DRM_ERROR("dispatch failed %d\n", ret);
                goto err;
@@ -4025,7 +3930,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
         * Ensure that the commands in the batch buffer are
         * finished before the interrupt fires
         */
-       flush_domains = i915_retire_commands(dev);
+       flush_domains = i915_retire_commands(dev, ring);
 
        i915_verify_inactive(dev, __FILE__, __LINE__);
 
@@ -4036,12 +3941,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
         * *some* interrupts representing completion of buffers that we can
         * wait on when trying to clear up gtt space).
         */
-       seqno = i915_add_request(dev, file_priv, flush_domains);
+       seqno = i915_add_request(dev, file_priv, flush_domains, ring);
        BUG_ON(seqno == 0);
        for (i = 0; i < args->buffer_count; i++) {
                struct drm_gem_object *obj = object_list[i];
+               obj_priv = to_intel_bo(obj);
 
-               i915_gem_object_move_to_active(obj, seqno);
+               i915_gem_object_move_to_active(obj, seqno, ring);
 #if WATCH_LRU
                DRM_INFO("%s: move to exec list %p\n", __func__, obj);
 #endif
@@ -4153,7 +4059,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
        exec2.DR4 = args->DR4;
        exec2.num_cliprects = args->num_cliprects;
        exec2.cliprects_ptr = args->cliprects_ptr;
-       exec2.flags = 0;
+       exec2.flags = I915_EXEC_RENDER;
 
        ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list);
        if (!ret) {
@@ -4239,7 +4145,20 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        int ret;
 
+       BUG_ON(obj_priv->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT);
+
        i915_verify_inactive(dev, __FILE__, __LINE__);
+
+       if (obj_priv->gtt_space != NULL) {
+               if (alignment == 0)
+                       alignment = i915_gem_get_gtt_alignment(obj);
+               if (obj_priv->gtt_offset & (alignment - 1)) {
+                       ret = i915_gem_object_unbind(obj);
+                       if (ret)
+                               return ret;
+               }
+       }
+
        if (obj_priv->gtt_space == NULL) {
                ret = i915_gem_object_bind_to_gtt(obj, alignment);
                if (ret)
@@ -4392,6 +4311,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
        struct drm_i915_gem_busy *args = data;
        struct drm_gem_object *obj;
        struct drm_i915_gem_object *obj_priv;
+       drm_i915_private_t *dev_priv = dev->dev_private;
 
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (obj == NULL) {
@@ -4406,7 +4326,10 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
         * actually unmasked, and our working set ends up being larger than
         * required.
         */
-       i915_gem_retire_requests(dev);
+       i915_gem_retire_requests(dev, &dev_priv->render_ring);
+
+       if (HAS_BSD(dev))
+               i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
 
        obj_priv = to_intel_bo(obj);
        /* Don't count being on the flushing list against the object being
@@ -4573,7 +4496,10 @@ i915_gem_idle(struct drm_device *dev)
 
        mutex_lock(&dev->struct_mutex);
 
-       if (dev_priv->mm.suspended || dev_priv->ring.ring_obj == NULL) {
+       if (dev_priv->mm.suspended ||
+                       (dev_priv->render_ring.gem_object == NULL) ||
+                       (HAS_BSD(dev) &&
+                        dev_priv->bsd_ring.gem_object == NULL)) {
                mutex_unlock(&dev->struct_mutex);
                return 0;
        }
@@ -4654,71 +4580,6 @@ err:
        return ret;
 }
 
-static int
-i915_gem_init_hws(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_gem_object *obj;
-       struct drm_i915_gem_object *obj_priv;
-       int ret;
-
-       /* If we need a physical address for the status page, it's already
-        * initialized at driver load time.
-        */
-       if (!I915_NEED_GFX_HWS(dev))
-               return 0;
-
-       obj = i915_gem_alloc_object(dev, 4096);
-       if (obj == NULL) {
-               DRM_ERROR("Failed to allocate status page\n");
-               ret = -ENOMEM;
-               goto err;
-       }
-       obj_priv = to_intel_bo(obj);
-       obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
-
-       ret = i915_gem_object_pin(obj, 4096);
-       if (ret != 0) {
-               drm_gem_object_unreference(obj);
-               goto err_unref;
-       }
-
-       dev_priv->status_gfx_addr = obj_priv->gtt_offset;
-
-       dev_priv->hw_status_page = kmap(obj_priv->pages[0]);
-       if (dev_priv->hw_status_page == NULL) {
-               DRM_ERROR("Failed to map status page.\n");
-               memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
-               ret = -EINVAL;
-               goto err_unpin;
-       }
-
-       if (HAS_PIPE_CONTROL(dev)) {
-               ret = i915_gem_init_pipe_control(dev);
-               if (ret)
-                       goto err_unpin;
-       }
-
-       dev_priv->hws_obj = obj;
-       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-       if (IS_GEN6(dev)) {
-               I915_WRITE(HWS_PGA_GEN6, dev_priv->status_gfx_addr);
-               I915_READ(HWS_PGA_GEN6); /* posting read */
-       } else {
-               I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
-               I915_READ(HWS_PGA); /* posting read */
-       }
-       DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
-
-       return 0;
-
-err_unpin:
-       i915_gem_object_unpin(obj);
-err_unref:
-       drm_gem_object_unreference(obj);
-err:
-       return 0;
-}
 
 static void
 i915_gem_cleanup_pipe_control(struct drm_device *dev)
@@ -4737,146 +4598,46 @@ i915_gem_cleanup_pipe_control(struct drm_device *dev)
        dev_priv->seqno_page = NULL;
 }
 
-static void
-i915_gem_cleanup_hws(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_gem_object *obj;
-       struct drm_i915_gem_object *obj_priv;
-
-       if (dev_priv->hws_obj == NULL)
-               return;
-
-       obj = dev_priv->hws_obj;
-       obj_priv = to_intel_bo(obj);
-
-       kunmap(obj_priv->pages[0]);
-       i915_gem_object_unpin(obj);
-       drm_gem_object_unreference(obj);
-       dev_priv->hws_obj = NULL;
-
-       memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
-       dev_priv->hw_status_page = NULL;
-
-       if (HAS_PIPE_CONTROL(dev))
-               i915_gem_cleanup_pipe_control(dev);
-
-       /* Write high address into HWS_PGA when disabling. */
-       I915_WRITE(HWS_PGA, 0x1ffff000);
-}
-
 int
 i915_gem_init_ringbuffer(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_gem_object *obj;
-       struct drm_i915_gem_object *obj_priv;
-       drm_i915_ring_buffer_t *ring = &dev_priv->ring;
        int ret;
-       u32 head;
-
-       ret = i915_gem_init_hws(dev);
-       if (ret != 0)
-               return ret;
 
-       obj = i915_gem_alloc_object(dev, 128 * 1024);
-       if (obj == NULL) {
-               DRM_ERROR("Failed to allocate ringbuffer\n");
-               i915_gem_cleanup_hws(dev);
-               return -ENOMEM;
-       }
-       obj_priv = to_intel_bo(obj);
+       dev_priv->render_ring = render_ring;
 
-       ret = i915_gem_object_pin(obj, 4096);
-       if (ret != 0) {
-               drm_gem_object_unreference(obj);
-               i915_gem_cleanup_hws(dev);
-               return ret;
+       if (!I915_NEED_GFX_HWS(dev)) {
+               dev_priv->render_ring.status_page.page_addr
+                       = dev_priv->status_page_dmah->vaddr;
+               memset(dev_priv->render_ring.status_page.page_addr,
+                               0, PAGE_SIZE);
        }
 
-       /* Set up the kernel mapping for the ring. */
-       ring->Size = obj->size;
-
-       ring->map.offset = dev->agp->base + obj_priv->gtt_offset;
-       ring->map.size = obj->size;
-       ring->map.type = 0;
-       ring->map.flags = 0;
-       ring->map.mtrr = 0;
-
-       drm_core_ioremap_wc(&ring->map, dev);
-       if (ring->map.handle == NULL) {
-               DRM_ERROR("Failed to map ringbuffer.\n");
-               memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
-               i915_gem_object_unpin(obj);
-               drm_gem_object_unreference(obj);
-               i915_gem_cleanup_hws(dev);
-               return -EINVAL;
-       }
-       ring->ring_obj = obj;
-       ring->virtual_start = ring->map.handle;
-
-       /* Stop the ring if it's running. */
-       I915_WRITE(PRB0_CTL, 0);
-       I915_WRITE(PRB0_TAIL, 0);
-       I915_WRITE(PRB0_HEAD, 0);
-
-       /* Initialize the ring. */
-       I915_WRITE(PRB0_START, obj_priv->gtt_offset);
-       head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-
-       /* G45 ring initialization fails to reset head to zero */
-       if (head != 0) {
-               DRM_ERROR("Ring head not reset to zero "
-                         "ctl %08x head %08x tail %08x start %08x\n",
-                         I915_READ(PRB0_CTL),
-                         I915_READ(PRB0_HEAD),
-                         I915_READ(PRB0_TAIL),
-                         I915_READ(PRB0_START));
-               I915_WRITE(PRB0_HEAD, 0);
-
-               DRM_ERROR("Ring head forced to zero "
-                         "ctl %08x head %08x tail %08x start %08x\n",
-                         I915_READ(PRB0_CTL),
-                         I915_READ(PRB0_HEAD),
-                         I915_READ(PRB0_TAIL),
-                         I915_READ(PRB0_START));
-       }
-
-       I915_WRITE(PRB0_CTL,
-                  ((obj->size - 4096) & RING_NR_PAGES) |
-                  RING_NO_REPORT |
-                  RING_VALID);
-
-       head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-
-       /* If the head is still not zero, the ring is dead */
-       if (head != 0) {
-               DRM_ERROR("Ring initialization failed "
-                         "ctl %08x head %08x tail %08x start %08x\n",
-                         I915_READ(PRB0_CTL),
-                         I915_READ(PRB0_HEAD),
-                         I915_READ(PRB0_TAIL),
-                         I915_READ(PRB0_START));
-               return -EIO;
+       if (HAS_PIPE_CONTROL(dev)) {
+               ret = i915_gem_init_pipe_control(dev);
+               if (ret)
+                       return ret;
        }
 
-       /* Update our cache of the ring state */
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               i915_kernel_lost_context(dev);
-       else {
-               ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-               ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->Size;
-       }
+       ret = intel_init_ring_buffer(dev, &dev_priv->render_ring);
+       if (ret)
+               goto cleanup_pipe_control;
 
-       if (IS_I9XX(dev) && !IS_GEN3(dev)) {
-               I915_WRITE(MI_MODE,
-                          (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH);
+       if (HAS_BSD(dev)) {
+               dev_priv->bsd_ring = bsd_ring;
+               ret = intel_init_ring_buffer(dev, &dev_priv->bsd_ring);
+               if (ret)
+                       goto cleanup_render_ring;
        }
 
        return 0;
+
+cleanup_render_ring:
+       intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
+cleanup_pipe_control:
+       if (HAS_PIPE_CONTROL(dev))
+               i915_gem_cleanup_pipe_control(dev);
+       return ret;
 }
 
 void
@@ -4884,17 +4645,11 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
 
-       if (dev_priv->ring.ring_obj == NULL)
-               return;
-
-       drm_core_ioremapfree(&dev_priv->ring.map, dev);
-
-       i915_gem_object_unpin(dev_priv->ring.ring_obj);
-       drm_gem_object_unreference(dev_priv->ring.ring_obj);
-       dev_priv->ring.ring_obj = NULL;
-       memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
-
-       i915_gem_cleanup_hws(dev);
+       intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
+       if (HAS_BSD(dev))
+               intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
+       if (HAS_PIPE_CONTROL(dev))
+               i915_gem_cleanup_pipe_control(dev);
 }
 
 int
@@ -4922,12 +4677,14 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
        }
 
        spin_lock(&dev_priv->mm.active_list_lock);
-       BUG_ON(!list_empty(&dev_priv->mm.active_list));
+       BUG_ON(!list_empty(&dev_priv->render_ring.active_list));
+       BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.active_list));
        spin_unlock(&dev_priv->mm.active_list_lock);
 
        BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
        BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
-       BUG_ON(!list_empty(&dev_priv->mm.request_list));
+       BUG_ON(!list_empty(&dev_priv->render_ring.request_list));
+       BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list));
        mutex_unlock(&dev->struct_mutex);
 
        drm_irq_install(dev);
@@ -4966,18 +4723,20 @@ i915_gem_load(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
 
        spin_lock_init(&dev_priv->mm.active_list_lock);
-       INIT_LIST_HEAD(&dev_priv->mm.active_list);
        INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
        INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list);
        INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
-       INIT_LIST_HEAD(&dev_priv->mm.request_list);
        INIT_LIST_HEAD(&dev_priv->mm.fence_list);
+       INIT_LIST_HEAD(&dev_priv->render_ring.active_list);
+       INIT_LIST_HEAD(&dev_priv->render_ring.request_list);
+       if (HAS_BSD(dev)) {
+               INIT_LIST_HEAD(&dev_priv->bsd_ring.active_list);
+               INIT_LIST_HEAD(&dev_priv->bsd_ring.request_list);
+       }
        for (i = 0; i < 16; i++)
                INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
        INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
                          i915_gem_retire_work_handler);
-       dev_priv->mm.next_gem_seqno = 1;
-
        spin_lock(&shrink_list_lock);
        list_add(&dev_priv->mm.shrink_list, &shrink_list);
        spin_unlock(&shrink_list_lock);
@@ -5209,7 +4968,9 @@ i915_gpu_is_active(struct drm_device *dev)
 
        spin_lock(&dev_priv->mm.active_list_lock);
        lists_empty = list_empty(&dev_priv->mm.flushing_list) &&
-                     list_empty(&dev_priv->mm.active_list);
+                     list_empty(&dev_priv->render_ring.active_list);
+       if (HAS_BSD(dev))
+               lists_empty &= list_empty(&dev_priv->bsd_ring.active_list);
        spin_unlock(&dev_priv->mm.active_list_lock);
 
        return !lists_empty;
@@ -5254,8 +5015,10 @@ rescan:
                        continue;
 
                spin_unlock(&shrink_list_lock);
+               i915_gem_retire_requests(dev, &dev_priv->render_ring);
 
-               i915_gem_retire_requests(dev);
+               if (HAS_BSD(dev))
+                       i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
 
                list_for_each_entry_safe(obj_priv, next_obj,
                                         &dev_priv->mm.inactive_list,
index 8c3f0802686dbbbba9bc38692681368095db662a..dba53d4b9fb3a11b7b76194e0fa6aec97211e966 100644 (file)
@@ -53,7 +53,7 @@
         I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
 
 /** Interrupts that we mask and unmask at runtime. */
-#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
+#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT | I915_BSD_USER_INTERRUPT)
 
 #define I915_PIPE_VBLANK_STATUS        (PIPE_START_VBLANK_INTERRUPT_STATUS |\
                                 PIPE_VBLANK_INTERRUPT_STATUS)
@@ -74,7 +74,7 @@ ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
        }
 }
 
-static inline void
+void
 ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
        if ((dev_priv->gt_irq_mask_reg & mask) != mask) {
@@ -115,7 +115,7 @@ i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
        }
 }
 
-static inline void
+void
 i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
        if ((dev_priv->irq_mask_reg & mask) != mask) {
@@ -278,10 +278,9 @@ static void i915_handle_rps_change(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 busy_up, busy_down, max_avg, min_avg;
-       u16 rgvswctl;
        u8 new_delay = dev_priv->cur_delay;
 
-       I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS) & ~MEMINT_EVAL_CHG);
+       I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG);
        busy_up = I915_READ(RCPREVBSYTUPAVG);
        busy_down = I915_READ(RCPREVBSYTDNAVG);
        max_avg = I915_READ(RCBMAXAVG);
@@ -300,27 +299,8 @@ static void i915_handle_rps_change(struct drm_device *dev)
                        new_delay = dev_priv->min_delay;
        }
 
-       DRM_DEBUG("rps change requested: %d -> %d\n",
-                 dev_priv->cur_delay, new_delay);
-
-       rgvswctl = I915_READ(MEMSWCTL);
-       if (rgvswctl & MEMCTL_CMD_STS) {
-               DRM_ERROR("gpu busy, RCS change rejected\n");
-               return; /* still busy with another command */
-       }
-
-       /* Program the new state */
-       rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
-               (new_delay << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
-       I915_WRITE(MEMSWCTL, rgvswctl);
-       POSTING_READ(MEMSWCTL);
-
-       rgvswctl |= MEMCTL_CMD_STS;
-       I915_WRITE(MEMSWCTL, rgvswctl);
-
-       dev_priv->cur_delay = new_delay;
-
-       DRM_DEBUG("rps changed\n");
+       if (ironlake_set_drps(dev, new_delay))
+               dev_priv->cur_delay = new_delay;
 
        return;
 }
@@ -331,6 +311,7 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
        int ret = IRQ_NONE;
        u32 de_iir, gt_iir, de_ier, pch_iir;
        struct drm_i915_master_private *master_priv;
+       struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
 
        /* disable master interrupt before clearing iir  */
        de_ier = I915_READ(DEIER);
@@ -354,13 +335,16 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
        }
 
        if (gt_iir & GT_PIPE_NOTIFY) {
-               u32 seqno = i915_get_gem_seqno(dev);
-               dev_priv->mm.irq_gem_seqno = seqno;
+               u32 seqno = render_ring->get_gem_seqno(dev, render_ring);
+               render_ring->irq_gem_seqno = seqno;
                trace_i915_gem_request_complete(dev, seqno);
-               DRM_WAKEUP(&dev_priv->irq_queue);
+               DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
                dev_priv->hangcheck_count = 0;
                mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
        }
+       if (gt_iir & GT_BSD_USER_INTERRUPT)
+               DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
+
 
        if (de_iir & DE_GSE)
                ironlake_opregion_gse_intr(dev);
@@ -388,7 +372,7 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
        }
 
        if (de_iir & DE_PCU_EVENT) {
-               I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS));
+               I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
                i915_handle_rps_change(dev);
        }
 
@@ -536,17 +520,18 @@ i915_ringbuffer_last_batch(struct drm_device *dev)
         */
        bbaddr = 0;
        head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-       ring = (u32 *)(dev_priv->ring.virtual_start + head);
+       ring = (u32 *)(dev_priv->render_ring.virtual_start + head);
 
-       while (--ring >= (u32 *)dev_priv->ring.virtual_start) {
+       while (--ring >= (u32 *)dev_priv->render_ring.virtual_start) {
                bbaddr = i915_get_bbaddr(dev, ring);
                if (bbaddr)
                        break;
        }
 
        if (bbaddr == 0) {
-               ring = (u32 *)(dev_priv->ring.virtual_start + dev_priv->ring.Size);
-               while (--ring >= (u32 *)dev_priv->ring.virtual_start) {
+               ring = (u32 *)(dev_priv->render_ring.virtual_start
+                               + dev_priv->render_ring.size);
+               while (--ring >= (u32 *)dev_priv->render_ring.virtual_start) {
                        bbaddr = i915_get_bbaddr(dev, ring);
                        if (bbaddr)
                                break;
@@ -587,7 +572,7 @@ static void i915_capture_error_state(struct drm_device *dev)
                return;
        }
 
-       error->seqno = i915_get_gem_seqno(dev);
+       error->seqno = i915_get_gem_seqno(dev, &dev_priv->render_ring);
        error->eir = I915_READ(EIR);
        error->pgtbl_er = I915_READ(PGTBL_ER);
        error->pipeastat = I915_READ(PIPEASTAT);
@@ -615,7 +600,9 @@ static void i915_capture_error_state(struct drm_device *dev)
        batchbuffer[0] = NULL;
        batchbuffer[1] = NULL;
        count = 0;
-       list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
+       list_for_each_entry(obj_priv,
+                       &dev_priv->render_ring.active_list, list) {
+
                struct drm_gem_object *obj = &obj_priv->base;
 
                if (batchbuffer[0] == NULL &&
@@ -639,7 +626,8 @@ static void i915_capture_error_state(struct drm_device *dev)
        error->batchbuffer[1] = i915_error_object_create(dev, batchbuffer[1]);
 
        /* Record the ringbuffer */
-       error->ringbuffer = i915_error_object_create(dev, dev_priv->ring.ring_obj);
+       error->ringbuffer = i915_error_object_create(dev,
+                       dev_priv->render_ring.gem_object);
 
        /* Record buffers on the active list. */
        error->active_bo = NULL;
@@ -651,7 +639,8 @@ static void i915_capture_error_state(struct drm_device *dev)
 
        if (error->active_bo) {
                int i = 0;
-               list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
+               list_for_each_entry(obj_priv,
+                               &dev_priv->render_ring.active_list, list) {
                        struct drm_gem_object *obj = &obj_priv->base;
 
                        error->active_bo[i].size = obj->size;
@@ -703,24 +692,13 @@ void i915_destroy_error_state(struct drm_device *dev)
                i915_error_state_free(dev, error);
 }
 
-/**
- * i915_handle_error - handle an error interrupt
- * @dev: drm device
- *
- * Do some basic checking of regsiter state at error interrupt time and
- * dump it to the syslog.  Also call i915_capture_error_state() to make
- * sure we get a record and make it available in debugfs.  Fire a uevent
- * so userspace knows something bad happened (should trigger collection
- * of a ring dump etc.).
- */
-static void i915_handle_error(struct drm_device *dev, bool wedged)
+static void i915_report_and_clear_eir(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 eir = I915_READ(EIR);
-       u32 pipea_stats = I915_READ(PIPEASTAT);
-       u32 pipeb_stats = I915_READ(PIPEBSTAT);
 
-       i915_capture_error_state(dev);
+       if (!eir)
+               return;
 
        printk(KERN_ERR "render error detected, EIR: 0x%08x\n",
               eir);
@@ -766,6 +744,9 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
        }
 
        if (eir & I915_ERROR_MEMORY_REFRESH) {
+               u32 pipea_stats = I915_READ(PIPEASTAT);
+               u32 pipeb_stats = I915_READ(PIPEBSTAT);
+
                printk(KERN_ERR "memory refresh error\n");
                printk(KERN_ERR "PIPEASTAT: 0x%08x\n",
                       pipea_stats);
@@ -822,6 +803,24 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
                I915_WRITE(EMR, I915_READ(EMR) | eir);
                I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
        }
+}
+
+/**
+ * i915_handle_error - handle an error interrupt
+ * @dev: drm device
+ *
+ * Do some basic checking of regsiter state at error interrupt time and
+ * dump it to the syslog.  Also call i915_capture_error_state() to make
+ * sure we get a record and make it available in debugfs.  Fire a uevent
+ * so userspace knows something bad happened (should trigger collection
+ * of a ring dump etc.).
+ */
+static void i915_handle_error(struct drm_device *dev, bool wedged)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       i915_capture_error_state(dev);
+       i915_report_and_clear_eir(dev);
 
        if (wedged) {
                atomic_set(&dev_priv->mm.wedged, 1);
@@ -829,7 +828,7 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
                /*
                 * Wakeup waiting processes so they don't hang
                 */
-               DRM_WAKEUP(&dev_priv->irq_queue);
+               DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
        }
 
        queue_work(dev_priv->wq, &dev_priv->error_work);
@@ -848,6 +847,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
        unsigned long irqflags;
        int irq_received;
        int ret = IRQ_NONE;
+       struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
 
        atomic_inc(&dev_priv->irq_received);
 
@@ -928,30 +928,42 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
                }
 
                if (iir & I915_USER_INTERRUPT) {
-                       u32 seqno = i915_get_gem_seqno(dev);
-                       dev_priv->mm.irq_gem_seqno = seqno;
+                       u32 seqno =
+                               render_ring->get_gem_seqno(dev, render_ring);
+                       render_ring->irq_gem_seqno = seqno;
                        trace_i915_gem_request_complete(dev, seqno);
-                       DRM_WAKEUP(&dev_priv->irq_queue);
+                       DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
                        dev_priv->hangcheck_count = 0;
                        mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
                }
 
-               if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
+               if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT))
+                       DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
+
+               if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
                        intel_prepare_page_flip(dev, 0);
+                       if (dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip_plane(dev, 0);
+               }
 
-               if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT)
+               if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
                        intel_prepare_page_flip(dev, 1);
+                       if (dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip_plane(dev, 1);
+               }
 
                if (pipea_stats & vblank_status) {
                        vblank++;
                        drm_handle_vblank(dev, 0);
-                       intel_finish_page_flip(dev, 0);
+                       if (!dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip(dev, 0);
                }
 
                if (pipeb_stats & vblank_status) {
                        vblank++;
                        drm_handle_vblank(dev, 1);
-                       intel_finish_page_flip(dev, 1);
+                       if (!dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip(dev, 1);
                }
 
                if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
@@ -984,7 +996,6 @@ static int i915_emit_irq(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-       RING_LOCALS;
 
        i915_kernel_lost_context(dev);
 
@@ -1006,43 +1017,13 @@ static int i915_emit_irq(struct drm_device * dev)
        return dev_priv->counter;
 }
 
-void i915_user_irq_get(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-       if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
-               if (HAS_PCH_SPLIT(dev))
-                       ironlake_enable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
-               else
-                       i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
-       }
-       spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
-}
-
-void i915_user_irq_put(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-       BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
-       if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
-               if (HAS_PCH_SPLIT(dev))
-                       ironlake_disable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
-               else
-                       i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
-       }
-       spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
-}
-
 void i915_trace_irq_get(struct drm_device *dev, u32 seqno)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
 
        if (dev_priv->trace_irq_seqno == 0)
-               i915_user_irq_get(dev);
+               render_ring->user_irq_get(dev, render_ring);
 
        dev_priv->trace_irq_seqno = seqno;
 }
@@ -1052,6 +1033,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
        int ret = 0;
+       struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
 
        DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr,
                  READ_BREADCRUMB(dev_priv));
@@ -1065,10 +1047,10 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
        if (master_priv->sarea_priv)
                master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
 
-       i915_user_irq_get(dev);
-       DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
+       render_ring->user_irq_get(dev, render_ring);
+       DRM_WAIT_ON(ret, dev_priv->render_ring.irq_queue, 3 * DRM_HZ,
                    READ_BREADCRUMB(dev_priv) >= irq_nr);
-       i915_user_irq_put(dev);
+       render_ring->user_irq_put(dev, render_ring);
 
        if (ret == -EBUSY) {
                DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
@@ -1087,7 +1069,7 @@ int i915_irq_emit(struct drm_device *dev, void *data,
        drm_i915_irq_emit_t *emit = data;
        int result;
 
-       if (!dev_priv || !dev_priv->ring.virtual_start) {
+       if (!dev_priv || !dev_priv->render_ring.virtual_start) {
                DRM_ERROR("called with no initialization\n");
                return -EINVAL;
        }
@@ -1233,9 +1215,12 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
        return -EINVAL;
 }
 
-struct drm_i915_gem_request *i915_get_tail_request(struct drm_device *dev) {
+struct drm_i915_gem_request *
+i915_get_tail_request(struct drm_device *dev)
+{
        drm_i915_private_t *dev_priv = dev->dev_private;
-       return list_entry(dev_priv->mm.request_list.prev, struct drm_i915_gem_request, list);
+       return list_entry(dev_priv->render_ring.request_list.prev,
+                       struct drm_i915_gem_request, list);
 }
 
 /**
@@ -1260,8 +1245,10 @@ void i915_hangcheck_elapsed(unsigned long data)
                acthd = I915_READ(ACTHD_I965);
 
        /* If all work is done then ACTHD clearly hasn't advanced. */
-       if (list_empty(&dev_priv->mm.request_list) ||
-                      i915_seqno_passed(i915_get_gem_seqno(dev), i915_get_tail_request(dev)->seqno)) {
+       if (list_empty(&dev_priv->render_ring.request_list) ||
+               i915_seqno_passed(i915_get_gem_seqno(dev,
+                               &dev_priv->render_ring),
+                       i915_get_tail_request(dev)->seqno)) {
                dev_priv->hangcheck_count = 0;
                return;
        }
@@ -1314,7 +1301,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
        /* enable kind of interrupts always enabled */
        u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
                           DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE;
-       u32 render_mask = GT_PIPE_NOTIFY;
+       u32 render_mask = GT_PIPE_NOTIFY | GT_BSD_USER_INTERRUPT;
        u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
                           SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
 
@@ -1328,7 +1315,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
        (void) I915_READ(DEIER);
 
        /* user interrupt should be enabled, but masked initial */
-       dev_priv->gt_irq_mask_reg = 0xffffffff;
+       dev_priv->gt_irq_mask_reg = ~render_mask;
        dev_priv->gt_irq_enable_reg = render_mask;
 
        I915_WRITE(GTIIR, I915_READ(GTIIR));
@@ -1391,7 +1378,10 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
        u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
        u32 error_mask;
 
-       DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+       DRM_INIT_WAITQUEUE(&dev_priv->render_ring.irq_queue);
+
+       if (HAS_BSD(dev))
+               DRM_INIT_WAITQUEUE(&dev_priv->bsd_ring.irq_queue);
 
        dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
@@ -1405,29 +1395,10 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
        dev_priv->pipestat[1] = 0;
 
        if (I915_HAS_HOTPLUG(dev)) {
-               u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-
-               /* Note HDMI and DP share bits */
-               if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
-                       hotplug_en |= HDMIB_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
-                       hotplug_en |= HDMIC_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
-                       hotplug_en |= HDMID_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
-                       hotplug_en |= SDVOC_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
-                       hotplug_en |= SDVOB_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
-                       hotplug_en |= CRT_HOTPLUG_INT_EN;
-               /* Ignore TV since it's buggy */
-
-               I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-
                /* Enable in IER... */
                enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
                /* and unmask in IMR */
-               i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT);
+               dev_priv->irq_mask_reg &= ~I915_DISPLAY_PORT_INTERRUPT;
        }
 
        /*
@@ -1445,16 +1416,41 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
        }
        I915_WRITE(EMR, error_mask);
 
-       /* Disable pipe interrupt enables, clear pending pipe status */
-       I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
-       I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
-       /* Clear pending interrupt status */
-       I915_WRITE(IIR, I915_READ(IIR));
-
-       I915_WRITE(IER, enable_mask);
        I915_WRITE(IMR, dev_priv->irq_mask_reg);
+       I915_WRITE(IER, enable_mask);
        (void) I915_READ(IER);
 
+       if (I915_HAS_HOTPLUG(dev)) {
+               u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+
+               /* Note HDMI and DP share bits */
+               if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMIB_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMID_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+                       hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+                       hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
+                       hotplug_en |= CRT_HOTPLUG_INT_EN;
+
+                       /* Programming the CRT detection parameters tends
+                          to generate a spurious hotplug event about three
+                          seconds later.  So just do it once.
+                       */
+                       if (IS_G4X(dev))
+                               hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
+                       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
+               }
+
+               /* Ignore TV since it's buggy */
+
+               I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+       }
+
        opregion_enable_asle(dev);
 
        return 0;
index f3e39cc46f0dd0c4e9dba3c130a05ce1dc5986cf..150400f405346de04d5693bfedc91d36f0a85a2c 100644 (file)
 #define   MI_OVERLAY_OFF       (0x2<<21)
 #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
 #define MI_DISPLAY_FLIP                MI_INSTR(0x14, 2)
+#define MI_DISPLAY_FLIP_I915   MI_INSTR(0x14, 1)
 #define   MI_DISPLAY_FLIP_PLANE(n) ((n) << 20)
 #define MI_STORE_DWORD_IMM     MI_INSTR(0x20, 1)
 #define   MI_MEM_VIRTUAL       (1 << 22) /* 965+ only */
 #define   I915_DEBUG_INTERRUPT                         (1<<2)
 #define   I915_USER_INTERRUPT                          (1<<1)
 #define   I915_ASLE_INTERRUPT                          (1<<0)
+#define   I915_BSD_USER_INTERRUPT                      (1<<25)
 #define EIR            0x020b0
 #define EMR            0x020b4
 #define ESR            0x020b8
 #define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
 #define BB_ADDR                0x02140 /* 8 bytes */
 #define GFX_FLSH_CNTL  0x02170 /* 915+ only */
+#define ECOSKPD                0x021d0
+#define   ECO_GATING_CX_ONLY   (1<<3)
+#define   ECO_FLIP_DONE                (1<<0)
+
+/* GEN6 interrupt control */
+#define GEN6_RENDER_HWSTAM     0x2098
+#define GEN6_RENDER_IMR                0x20a8
+#define   GEN6_RENDER_CONTEXT_SWITCH_INTERRUPT         (1 << 8)
+#define   GEN6_RENDER_PPGTT_PAGE_FAULT                 (1 << 7)
+#define   GEN6_RENDER TIMEOUT_COUNTER_EXPIRED          (1 << 6)
+#define   GEN6_RENDER_L3_PARITY_ERROR                  (1 << 5)
+#define   GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT    (1 << 4)
+#define   GEN6_RENDER_COMMAND_PARSER_MASTER_ERROR      (1 << 3)
+#define   GEN6_RENDER_SYNC_STATUS                      (1 << 2)
+#define   GEN6_RENDER_DEBUG_INTERRUPT                  (1 << 1)
+#define   GEN6_RENDER_USER_INTERRUPT                   (1 << 0)
+
+#define GEN6_BLITTER_HWSTAM    0x22098
+#define GEN6_BLITTER_IMR       0x220a8
+#define   GEN6_BLITTER_MI_FLUSH_DW_NOTIFY_INTERRUPT    (1 << 26)
+#define   GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR     (1 << 25)
+#define   GEN6_BLITTER_SYNC_STATUS                     (1 << 24)
+#define   GEN6_BLITTER_USER_INTERRUPT                  (1 << 22)
+/*
+ * BSD (bit stream decoder instruction and interrupt control register defines
+ * (G4X and Ironlake only)
+ */
 
+#define BSD_RING_TAIL          0x04030
+#define BSD_RING_HEAD          0x04034
+#define BSD_RING_START         0x04038
+#define BSD_RING_CTL           0x0403c
+#define BSD_RING_ACTHD         0x04074
+#define BSD_HWS_PGA            0x04080
 
 /*
  * Framebuffer compression (915+ only)
 #define DCC_CHANNEL_XOR_DISABLE                                (1 << 10)
 #define DCC_CHANNEL_XOR_BIT_17                         (1 << 9)
 
+/** Pineview MCH register contains DDR3 setting */
+#define CSHRDDR3CTL            0x101a8
+#define CSHRDDR3CTL_DDR3       (1 << 2)
+
 /** 965 MCH register controlling DRAM channel configuration */
 #define C0DRB3                 0x10206
 #define C1DRB3                 0x10606
 #define CLKCFG_MEM_800                                 (3 << 4)
 #define CLKCFG_MEM_MASK                                        (7 << 4)
 
+#define TR1                    0x11006
+#define TSFS                   0x11020
+#define   TSFS_SLOPE_MASK      0x0000ff00
+#define   TSFS_SLOPE_SHIFT     8
+#define   TSFS_INTR_MASK       0x000000ff
+
 #define CRSTANDVID             0x11100
 #define PXVFREQ_BASE           0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */
 #define   PXVFREQ_PX_MASK      0x7f000000
 #define   MEMSTAT_SRC_CTL_STDBY 3
 #define RCPREVBSYTUPAVG                0x113b8
 #define RCPREVBSYTDNAVG                0x113bc
+#define SDEW                   0x1124c
+#define CSIEW0                 0x11250
+#define CSIEW1                 0x11254
+#define CSIEW2                 0x11258
+#define PEW                    0x1125c
+#define DEW                    0x11270
+#define MCHAFE                 0x112c0
+#define CSIEC                  0x112e0
+#define DMIEC                  0x112e4
+#define DDREC                  0x112e8
+#define PEG0EC                 0x112ec
+#define PEG1EC                 0x112f0
+#define GFXEC                  0x112f4
+#define RPPREVBSYTUPAVG                0x113b8
+#define RPPREVBSYTDNAVG                0x113bc
+#define ECR                    0x11600
+#define   ECR_GPFE             (1<<31)
+#define   ECR_IMONE            (1<<30)
+#define   ECR_CAP_MASK         0x0000001f /* Event range, 0-31 */
+#define OGW0                   0x11608
+#define OGW1                   0x1160c
+#define EG0                    0x11610
+#define EG1                    0x11614
+#define EG2                    0x11618
+#define EG3                    0x1161c
+#define EG4                    0x11620
+#define EG5                    0x11624
+#define EG6                    0x11628
+#define EG7                    0x1162c
+#define PXW                    0x11664
+#define PXWL                   0x11680
+#define LCFUSE02               0x116c0
+#define   LCFUSE_HIV_MASK      0x000000ff
+#define CSIPLL0                        0x12c10
+#define DDRMPLL1               0X12c20
 #define PEG_BAND_GAP_DATA      0x14d68
 
 /*
 #define CRT_HOTPLUG_DETECT_DELAY_2G            (1 << 4)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV       (0 << 2)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV       (1 << 2)
-#define CRT_HOTPLUG_MASK                       (0x3fc) /* Bits 9-2 */
-#define CRT_FORCE_HOTPLUG_MASK                 0xfffffe1f
 
 #define PORT_HOTPLUG_STAT      0x61114
 #define   HDMIB_HOTPLUG_INT_STATUS             (1 << 29)
 #define GT_PIPE_NOTIFY         (1 << 4)
 #define GT_SYNC_STATUS          (1 << 2)
 #define GT_USER_INTERRUPT       (1 << 0)
+#define GT_BSD_USER_INTERRUPT   (1 << 5)
+
 
 #define GTISR   0x44010
 #define GTIMR   0x44014
 #define  SDVO_ENCODING          (0)
 #define  TMDS_ENCODING          (2 << 10)
 #define  NULL_PACKET_VSYNC_ENABLE       (1 << 9)
+/* CPT */
+#define  HDMI_MODE_SELECT      (1 << 9)
+#define  DVI_MODE_SELECT       (0)
 #define  SDVOB_BORDER_ENABLE    (1 << 7)
 #define  AUDIO_ENABLE           (1 << 6)
 #define  VSYNC_ACTIVE_HIGH      (1 << 4)
index 9e4c45f68d6edd2af9812cef1c5fc89453e52f55..fab21760dd57857cef544f205c44766d08a923ff 100644 (file)
@@ -53,23 +53,6 @@ TRACE_EVENT(i915_gem_object_bind,
                      __entry->obj, __entry->gtt_offset)
 );
 
-TRACE_EVENT(i915_gem_object_clflush,
-
-           TP_PROTO(struct drm_gem_object *obj),
-
-           TP_ARGS(obj),
-
-           TP_STRUCT__entry(
-                            __field(struct drm_gem_object *, obj)
-                            ),
-
-           TP_fast_assign(
-                          __entry->obj = obj;
-                          ),
-
-           TP_printk("obj=%p", __entry->obj)
-);
-
 TRACE_EVENT(i915_gem_object_change_domain,
 
            TP_PROTO(struct drm_gem_object *obj, uint32_t old_read_domains, uint32_t old_write_domain),
@@ -132,6 +115,13 @@ DECLARE_EVENT_CLASS(i915_gem_object,
            TP_printk("obj=%p", __entry->obj)
 );
 
+DEFINE_EVENT(i915_gem_object, i915_gem_object_clflush,
+
+           TP_PROTO(struct drm_gem_object *obj),
+
+           TP_ARGS(obj)
+);
+
 DEFINE_EVENT(i915_gem_object, i915_gem_object_unbind,
 
            TP_PROTO(struct drm_gem_object *obj),
index 4c748d8f73d63a4da25f8ea10a981f7fc8860c2e..96f75d7f663319c77ed5f77d279c8cc4794591d2 100644 (file)
@@ -95,6 +95,16 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
        panel_fixed_mode->clock = dvo_timing->clock * 10;
        panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
 
+       if (dvo_timing->hsync_positive)
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
+       else
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
+
+       if (dvo_timing->vsync_positive)
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
+       else
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
+
        /* Some VBTs have bogus h/vtotal values */
        if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
                panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
index e16ac5a28c3cb178550f4f1763ea81fdd25d801e..ee0732b222a1a5e6e9e6fe0ae50c001867006298 100644 (file)
@@ -217,7 +217,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 hotplug_en;
+       u32 hotplug_en, orig, stat;
+       bool ret = false;
        int i, tries = 0;
 
        if (HAS_PCH_SPLIT(dev))
@@ -232,15 +233,9 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
                tries = 2;
        else
                tries = 1;
-       hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-       hotplug_en &= CRT_FORCE_HOTPLUG_MASK;
+       hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN);
        hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
 
-       if (IS_G4X(dev))
-               hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
-
-       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-
        for (i = 0; i < tries ; i++) {
                unsigned long timeout;
                /* turn on the FORCE_DETECT */
@@ -255,11 +250,17 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
                } while (time_after(timeout, jiffies));
        }
 
-       if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) !=
-           CRT_HOTPLUG_MONITOR_NONE)
-               return true;
+       stat = I915_READ(PORT_HOTPLUG_STAT);
+       if ((stat & CRT_HOTPLUG_MONITOR_MASK) != CRT_HOTPLUG_MONITOR_NONE)
+               ret = true;
+
+       /* clear the interrupt we just generated, if any */
+       I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS);
+
+       /* and put the bits back */
+       I915_WRITE(PORT_HOTPLUG_EN, orig);
 
-       return false;
+       return ret;
 }
 
 static bool intel_crt_detect_ddc(struct drm_encoder *encoder)
@@ -569,7 +570,7 @@ void intel_crt_init(struct drm_device *dev)
                                   (1 << INTEL_ANALOG_CLONE_BIT) |
                                   (1 << INTEL_SDVO_LVDS_CLONE_BIT);
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
-       connector->interlace_allowed = 0;
+       connector->interlace_allowed = 1;
        connector->doublescan_allowed = 0;
 
        drm_encoder_helper_add(&intel_encoder->enc, &intel_crt_helper_funcs);
index f469a84cacfd92951ce866257699176ef37a21e5..68dcf36e2793f51fa42aeecb9b67037aa8515205 100644 (file)
@@ -1029,19 +1029,28 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 void i8xx_disable_fbc(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned long timeout = jiffies + msecs_to_jiffies(1);
        u32 fbc_ctl;
 
        if (!I915_HAS_FBC(dev))
                return;
 
+       if (!(I915_READ(FBC_CONTROL) & FBC_CTL_EN))
+               return; /* Already off, just return */
+
        /* Disable compression */
        fbc_ctl = I915_READ(FBC_CONTROL);
        fbc_ctl &= ~FBC_CTL_EN;
        I915_WRITE(FBC_CONTROL, fbc_ctl);
 
        /* Wait for compressing bit to clear */
-       while (I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING)
-               ; /* nothing */
+       while (I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) {
+               if (time_after(jiffies, timeout)) {
+                       DRM_DEBUG_DRIVER("FBC idle timed out\n");
+                       break;
+               }
+               ; /* do nothing */
+       }
 
        intel_wait_for_vblank(dev);
 
@@ -1239,10 +1248,11 @@ static void intel_update_fbc(struct drm_crtc *crtc,
        return;
 
 out_disable:
-       DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
        /* Multiple disables should be harmless */
-       if (intel_fbc_enabled(dev))
+       if (intel_fbc_enabled(dev)) {
+               DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
                intel_disable_fbc(dev);
+       }
 }
 
 static int
@@ -1386,7 +1396,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        Start = obj_priv->gtt_offset;
        Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
 
-       DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+       DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
+                     Start, Offset, x, y, crtc->fb->pitch);
        I915_WRITE(dspstride, crtc->fb->pitch);
        if (IS_I965G(dev)) {
                I915_WRITE(dspbase, Offset);
@@ -2345,6 +2356,8 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
                if (mode->clock * 3 > 27000 * 4)
                        return MODE_CLOCK_HIGH;
        }
+
+       drm_mode_set_crtcinfo(adjusted_mode, 0);
        return true;
 }
 
@@ -2629,6 +2642,7 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
 
 struct cxsr_latency {
        int is_desktop;
+       int is_ddr3;
        unsigned long fsb_freq;
        unsigned long mem_freq;
        unsigned long display_sr;
@@ -2638,33 +2652,45 @@ struct cxsr_latency {
 };
 
 static struct cxsr_latency cxsr_latency_table[] = {
-       {1, 800, 400, 3382, 33382, 3983, 33983},    /* DDR2-400 SC */
-       {1, 800, 667, 3354, 33354, 3807, 33807},    /* DDR2-667 SC */
-       {1, 800, 800, 3347, 33347, 3763, 33763},    /* DDR2-800 SC */
-
-       {1, 667, 400, 3400, 33400, 4021, 34021},    /* DDR2-400 SC */
-       {1, 667, 667, 3372, 33372, 3845, 33845},    /* DDR2-667 SC */
-       {1, 667, 800, 3386, 33386, 3822, 33822},    /* DDR2-800 SC */
-
-       {1, 400, 400, 3472, 33472, 4173, 34173},    /* DDR2-400 SC */
-       {1, 400, 667, 3443, 33443, 3996, 33996},    /* DDR2-667 SC */
-       {1, 400, 800, 3430, 33430, 3946, 33946},    /* DDR2-800 SC */
-
-       {0, 800, 400, 3438, 33438, 4065, 34065},    /* DDR2-400 SC */
-       {0, 800, 667, 3410, 33410, 3889, 33889},    /* DDR2-667 SC */
-       {0, 800, 800, 3403, 33403, 3845, 33845},    /* DDR2-800 SC */
-
-       {0, 667, 400, 3456, 33456, 4103, 34106},    /* DDR2-400 SC */
-       {0, 667, 667, 3428, 33428, 3927, 33927},    /* DDR2-667 SC */
-       {0, 667, 800, 3443, 33443, 3905, 33905},    /* DDR2-800 SC */
-
-       {0, 400, 400, 3528, 33528, 4255, 34255},    /* DDR2-400 SC */
-       {0, 400, 667, 3500, 33500, 4079, 34079},    /* DDR2-667 SC */
-       {0, 400, 800, 3487, 33487, 4029, 34029},    /* DDR2-800 SC */
+       {1, 0, 800, 400, 3382, 33382, 3983, 33983},    /* DDR2-400 SC */
+       {1, 0, 800, 667, 3354, 33354, 3807, 33807},    /* DDR2-667 SC */
+       {1, 0, 800, 800, 3347, 33347, 3763, 33763},    /* DDR2-800 SC */
+       {1, 1, 800, 667, 6420, 36420, 6873, 36873},    /* DDR3-667 SC */
+       {1, 1, 800, 800, 5902, 35902, 6318, 36318},    /* DDR3-800 SC */
+
+       {1, 0, 667, 400, 3400, 33400, 4021, 34021},    /* DDR2-400 SC */
+       {1, 0, 667, 667, 3372, 33372, 3845, 33845},    /* DDR2-667 SC */
+       {1, 0, 667, 800, 3386, 33386, 3822, 33822},    /* DDR2-800 SC */
+       {1, 1, 667, 667, 6438, 36438, 6911, 36911},    /* DDR3-667 SC */
+       {1, 1, 667, 800, 5941, 35941, 6377, 36377},    /* DDR3-800 SC */
+
+       {1, 0, 400, 400, 3472, 33472, 4173, 34173},    /* DDR2-400 SC */
+       {1, 0, 400, 667, 3443, 33443, 3996, 33996},    /* DDR2-667 SC */
+       {1, 0, 400, 800, 3430, 33430, 3946, 33946},    /* DDR2-800 SC */
+       {1, 1, 400, 667, 6509, 36509, 7062, 37062},    /* DDR3-667 SC */
+       {1, 1, 400, 800, 5985, 35985, 6501, 36501},    /* DDR3-800 SC */
+
+       {0, 0, 800, 400, 3438, 33438, 4065, 34065},    /* DDR2-400 SC */
+       {0, 0, 800, 667, 3410, 33410, 3889, 33889},    /* DDR2-667 SC */
+       {0, 0, 800, 800, 3403, 33403, 3845, 33845},    /* DDR2-800 SC */
+       {0, 1, 800, 667, 6476, 36476, 6955, 36955},    /* DDR3-667 SC */
+       {0, 1, 800, 800, 5958, 35958, 6400, 36400},    /* DDR3-800 SC */
+
+       {0, 0, 667, 400, 3456, 33456, 4103, 34106},    /* DDR2-400 SC */
+       {0, 0, 667, 667, 3428, 33428, 3927, 33927},    /* DDR2-667 SC */
+       {0, 0, 667, 800, 3443, 33443, 3905, 33905},    /* DDR2-800 SC */
+       {0, 1, 667, 667, 6494, 36494, 6993, 36993},    /* DDR3-667 SC */
+       {0, 1, 667, 800, 5998, 35998, 6460, 36460},    /* DDR3-800 SC */
+
+       {0, 0, 400, 400, 3528, 33528, 4255, 34255},    /* DDR2-400 SC */
+       {0, 0, 400, 667, 3500, 33500, 4079, 34079},    /* DDR2-667 SC */
+       {0, 0, 400, 800, 3487, 33487, 4029, 34029},    /* DDR2-800 SC */
+       {0, 1, 400, 667, 6566, 36566, 7145, 37145},    /* DDR3-667 SC */
+       {0, 1, 400, 800, 6042, 36042, 6584, 36584},    /* DDR3-800 SC */
 };
 
-static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb,
-                                                  int mem)
+static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int is_ddr3, 
+                                                  int fsb, int mem)
 {
        int i;
        struct cxsr_latency *latency;
@@ -2675,6 +2701,7 @@ static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb,
        for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) {
                latency = &cxsr_latency_table[i];
                if (is_desktop == latency->is_desktop &&
+                   is_ddr3 == latency->is_ddr3 &&
                    fsb == latency->fsb_freq && mem == latency->mem_freq)
                        return latency;
        }
@@ -2789,8 +2816,8 @@ static void pineview_update_wm(struct drm_device *dev,  int planea_clock,
        struct cxsr_latency *latency;
        int sr_clock;
 
-       latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->fsb_freq,
-                                        dev_priv->mem_freq);
+       latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, 
+                                        dev_priv->fsb_freq, dev_priv->mem_freq);
        if (!latency) {
                DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
                pineview_disable_cxsr(dev);
@@ -2943,11 +2970,13 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
                if (srwm < 0)
                        srwm = 1;
                srwm &= 0x3f;
-               I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+               if (IS_I965GM(dev))
+                       I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
        } else {
                /* Turn off self refresh if both pipes are enabled */
-               I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
-                                       & ~FW_BLC_SELF_EN);
+               if (IS_I965GM(dev))
+                       I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
+                                  & ~FW_BLC_SELF_EN);
        }
 
        DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
@@ -3626,6 +3655,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                        pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
        }
 
+       dspcntr |= DISPLAY_PLANE_ENABLE;
+       pipeconf |= PIPEACONF_ENABLE;
+       dpll |= DPLL_VCO_ENABLE;
+
+
        /* Disable the panel fitter if it was on our pipe */
        if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe)
                I915_WRITE(PFIT_CONTROL, 0);
@@ -3772,6 +3806,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                }
        }
 
+       if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+               pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
+               /* the chip adds 2 halflines automatically */
+               adjusted_mode->crtc_vdisplay -= 1;
+               adjusted_mode->crtc_vtotal -= 1;
+               adjusted_mode->crtc_vblank_start -= 1;
+               adjusted_mode->crtc_vblank_end -= 1;
+               adjusted_mode->crtc_vsync_end -= 1;
+               adjusted_mode->crtc_vsync_start -= 1;
+       } else
+               pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */
+
        I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
                   ((adjusted_mode->crtc_htotal - 1) << 16));
        I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
@@ -3934,6 +3980,13 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
                        DRM_ERROR("failed to pin cursor bo\n");
                        goto fail_locked;
                }
+
+               ret = i915_gem_object_set_to_gtt_domain(bo, 0);
+               if (ret) {
+                       DRM_ERROR("failed to move cursor bo into the GTT\n");
+                       goto fail_unpin;
+               }
+
                addr = obj_priv->gtt_offset;
        } else {
                ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
@@ -3977,6 +4030,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        intel_crtc->cursor_bo = bo;
 
        return 0;
+fail_unpin:
+       i915_gem_object_unpin(bo);
 fail_locked:
        mutex_unlock(&dev->struct_mutex);
 fail:
@@ -4430,27 +4485,31 @@ static void intel_idle_update(struct work_struct *work)
        struct drm_device *dev = dev_priv->dev;
        struct drm_crtc *crtc;
        struct intel_crtc *intel_crtc;
+       int enabled = 0;
 
        if (!i915_powersave)
                return;
 
        mutex_lock(&dev->struct_mutex);
 
-       if (IS_I945G(dev) || IS_I945GM(dev)) {
-               DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
-               I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
-       }
+       i915_update_gfx_val(dev_priv);
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                /* Skip inactive CRTCs */
                if (!crtc->fb)
                        continue;
 
+               enabled++;
                intel_crtc = to_intel_crtc(crtc);
                if (!intel_crtc->busy)
                        intel_decrease_pllclock(crtc);
        }
 
+       if ((enabled == 1) && (IS_I945G(dev) || IS_I945GM(dev))) {
+               DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
+               I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
+       }
+
        mutex_unlock(&dev->struct_mutex);
 }
 
@@ -4546,10 +4605,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
        kfree(work);
 }
 
-void intel_finish_page_flip(struct drm_device *dev, int pipe)
+static void do_intel_finish_page_flip(struct drm_device *dev,
+                                     struct drm_crtc *crtc)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_unpin_work *work;
        struct drm_i915_gem_object *obj_priv;
@@ -4564,12 +4623,6 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
        spin_lock_irqsave(&dev->event_lock, flags);
        work = intel_crtc->unpin_work;
        if (work == NULL || !work->pending) {
-               if (work && !work->pending) {
-                       obj_priv = to_intel_bo(work->pending_flip_obj);
-                       DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n",
-                                        obj_priv,
-                                        atomic_read(&obj_priv->pending_flip));
-               }
                spin_unlock_irqrestore(&dev->event_lock, flags);
                return;
        }
@@ -4599,6 +4652,22 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
        schedule_work(&work->work);
 }
 
+void intel_finish_page_flip(struct drm_device *dev, int pipe)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+
+       do_intel_finish_page_flip(dev, crtc);
+}
+
+void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
+
+       do_intel_finish_page_flip(dev, crtc);
+}
+
 void intel_prepare_page_flip(struct drm_device *dev, int plane)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
@@ -4629,14 +4698,12 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        unsigned long flags;
        int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
        int ret, pipesrc;
-       RING_LOCALS;
+       u32 flip_mask;
 
        work = kzalloc(sizeof *work, GFP_KERNEL);
        if (work == NULL)
                return -ENOMEM;
 
-       mutex_lock(&dev->struct_mutex);
-
        work->event = event;
        work->dev = crtc->dev;
        intel_fb = to_intel_framebuffer(crtc->fb);
@@ -4646,10 +4713,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        /* We borrow the event spin lock for protecting unpin_work */
        spin_lock_irqsave(&dev->event_lock, flags);
        if (intel_crtc->unpin_work) {
-               DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
                spin_unlock_irqrestore(&dev->event_lock, flags);
                kfree(work);
-               mutex_unlock(&dev->struct_mutex);
+
+               DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
                return -EBUSY;
        }
        intel_crtc->unpin_work = work;
@@ -4658,13 +4725,19 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        intel_fb = to_intel_framebuffer(fb);
        obj = intel_fb->obj;
 
+       mutex_lock(&dev->struct_mutex);
        ret = intel_pin_and_fence_fb_obj(dev, obj);
        if (ret != 0) {
-               DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
-                         to_intel_bo(obj));
-               kfree(work);
-               intel_crtc->unpin_work = NULL;
                mutex_unlock(&dev->struct_mutex);
+
+               spin_lock_irqsave(&dev->event_lock, flags);
+               intel_crtc->unpin_work = NULL;
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+
+               kfree(work);
+
+               DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
+                                to_intel_bo(obj));
                return ret;
        }
 
@@ -4679,15 +4752,28 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        atomic_inc(&obj_priv->pending_flip);
        work->pending_flip_obj = obj;
 
+       if (intel_crtc->plane)
+               flip_mask = I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
+       else
+               flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT;
+
+       /* Wait for any previous flip to finish */
+       if (IS_GEN3(dev))
+               while (I915_READ(ISR) & flip_mask)
+                       ;
+
        BEGIN_LP_RING(4);
-       OUT_RING(MI_DISPLAY_FLIP |
-                MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-       OUT_RING(fb->pitch);
        if (IS_I965G(dev)) {
+               OUT_RING(MI_DISPLAY_FLIP |
+                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+               OUT_RING(fb->pitch);
                OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
                pipesrc = I915_READ(pipesrc_reg); 
                OUT_RING(pipesrc & 0x0fff0fff);
        } else {
+               OUT_RING(MI_DISPLAY_FLIP_I915 |
+                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+               OUT_RING(fb->pitch);
                OUT_RING(obj_priv->gtt_offset);
                OUT_RING(MI_NOOP);
        }
@@ -5023,10 +5109,32 @@ err_unref:
        return NULL;
 }
 
+bool ironlake_set_drps(struct drm_device *dev, u8 val)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u16 rgvswctl;
+
+       rgvswctl = I915_READ16(MEMSWCTL);
+       if (rgvswctl & MEMCTL_CMD_STS) {
+               DRM_DEBUG("gpu busy, RCS change rejected\n");
+               return false; /* still busy with another command */
+       }
+
+       rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
+               (val << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
+       I915_WRITE16(MEMSWCTL, rgvswctl);
+       POSTING_READ16(MEMSWCTL);
+
+       rgvswctl |= MEMCTL_CMD_STS;
+       I915_WRITE16(MEMSWCTL, rgvswctl);
+
+       return true;
+}
+
 void ironlake_enable_drps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 rgvmodectl = I915_READ(MEMMODECTL), rgvswctl;
+       u32 rgvmodectl = I915_READ(MEMMODECTL);
        u8 fmax, fmin, fstart, vstart;
        int i = 0;
 
@@ -5045,13 +5153,21 @@ void ironlake_enable_drps(struct drm_device *dev)
        fmin = (rgvmodectl & MEMMODE_FMIN_MASK);
        fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
                MEMMODE_FSTART_SHIFT;
+       fstart = fmax;
+
        vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
                PXVFREQ_PX_SHIFT;
 
-       dev_priv->max_delay = fstart; /* can't go to fmax w/o IPS */
+       dev_priv->fmax = fstart; /* IPS callback will increase this */
+       dev_priv->fstart = fstart;
+
+       dev_priv->max_delay = fmax;
        dev_priv->min_delay = fmin;
        dev_priv->cur_delay = fstart;
 
+       DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", fmax, fmin,
+                        fstart);
+
        I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN);
 
        /*
@@ -5073,20 +5189,19 @@ void ironlake_enable_drps(struct drm_device *dev)
        }
        msleep(1);
 
-       rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
-               (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
-       I915_WRITE(MEMSWCTL, rgvswctl);
-       POSTING_READ(MEMSWCTL);
+       ironlake_set_drps(dev, fstart);
 
-       rgvswctl |= MEMCTL_CMD_STS;
-       I915_WRITE(MEMSWCTL, rgvswctl);
+       dev_priv->last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) +
+               I915_READ(0x112e0);
+       dev_priv->last_time1 = jiffies_to_msecs(jiffies);
+       dev_priv->last_count2 = I915_READ(0x112f4);
+       getrawmonotonic(&dev_priv->last_time2);
 }
 
 void ironlake_disable_drps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 rgvswctl;
-       u8 fstart;
+       u16 rgvswctl = I915_READ16(MEMSWCTL);
 
        /* Ack interrupts, disable EFC interrupt */
        I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
@@ -5096,11 +5211,7 @@ void ironlake_disable_drps(struct drm_device *dev)
        I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT);
 
        /* Go back to the starting frequency */
-       fstart = (I915_READ(MEMMODECTL) & MEMMODE_FSTART_MASK) >>
-               MEMMODE_FSTART_SHIFT;
-       rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
-               (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
-       I915_WRITE(MEMSWCTL, rgvswctl);
+       ironlake_set_drps(dev, dev_priv->fstart);
        msleep(1);
        rgvswctl |= MEMCTL_CMD_STS;
        I915_WRITE(MEMSWCTL, rgvswctl);
@@ -5108,6 +5219,92 @@ void ironlake_disable_drps(struct drm_device *dev)
 
 }
 
+static unsigned long intel_pxfreq(u32 vidfreq)
+{
+       unsigned long freq;
+       int div = (vidfreq & 0x3f0000) >> 16;
+       int post = (vidfreq & 0x3000) >> 12;
+       int pre = (vidfreq & 0x7);
+
+       if (!pre)
+               return 0;
+
+       freq = ((div * 133333) / ((1<<post) * pre));
+
+       return freq;
+}
+
+void intel_init_emon(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 lcfuse;
+       u8 pxw[16];
+       int i;
+
+       /* Disable to program */
+       I915_WRITE(ECR, 0);
+       POSTING_READ(ECR);
+
+       /* Program energy weights for various events */
+       I915_WRITE(SDEW, 0x15040d00);
+       I915_WRITE(CSIEW0, 0x007f0000);
+       I915_WRITE(CSIEW1, 0x1e220004);
+       I915_WRITE(CSIEW2, 0x04000004);
+
+       for (i = 0; i < 5; i++)
+               I915_WRITE(PEW + (i * 4), 0);
+       for (i = 0; i < 3; i++)
+               I915_WRITE(DEW + (i * 4), 0);
+
+       /* Program P-state weights to account for frequency power adjustment */
+       for (i = 0; i < 16; i++) {
+               u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4));
+               unsigned long freq = intel_pxfreq(pxvidfreq);
+               unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >>
+                       PXVFREQ_PX_SHIFT;
+               unsigned long val;
+
+               val = vid * vid;
+               val *= (freq / 1000);
+               val *= 255;
+               val /= (127*127*900);
+               if (val > 0xff)
+                       DRM_ERROR("bad pxval: %ld\n", val);
+               pxw[i] = val;
+       }
+       /* Render standby states get 0 weight */
+       pxw[14] = 0;
+       pxw[15] = 0;
+
+       for (i = 0; i < 4; i++) {
+               u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) |
+                       (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]);
+               I915_WRITE(PXW + (i * 4), val);
+       }
+
+       /* Adjust magic regs to magic values (more experimental results) */
+       I915_WRITE(OGW0, 0);
+       I915_WRITE(OGW1, 0);
+       I915_WRITE(EG0, 0x00007f00);
+       I915_WRITE(EG1, 0x0000000e);
+       I915_WRITE(EG2, 0x000e0000);
+       I915_WRITE(EG3, 0x68000300);
+       I915_WRITE(EG4, 0x42000000);
+       I915_WRITE(EG5, 0x00140031);
+       I915_WRITE(EG6, 0);
+       I915_WRITE(EG7, 0);
+
+       for (i = 0; i < 8; i++)
+               I915_WRITE(PXWL + (i * 4), 0);
+
+       /* Enable PMON + select events */
+       I915_WRITE(ECR, 0x80000019);
+
+       lcfuse = I915_READ(LCFUSE02);
+
+       dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
+}
+
 void intel_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5277,11 +5474,13 @@ static void intel_init_display(struct drm_device *dev)
                        dev_priv->display.update_wm = NULL;
        } else if (IS_PINEVIEW(dev)) {
                if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
+                                           dev_priv->is_ddr3,
                                            dev_priv->fsb_freq,
                                            dev_priv->mem_freq)) {
                        DRM_INFO("failed to find known CxSR latency "
-                                "(found fsb freq %d, mem freq %d), "
+                                "(found ddr%s fsb freq %d, mem freq %d), "
                                 "disabling CxSR\n",
+                                (dev_priv->is_ddr3 == 1) ? "3": "2",
                                 dev_priv->fsb_freq, dev_priv->mem_freq);
                        /* Disable CxSR and never update its watermark again */
                        pineview_disable_cxsr(dev);
@@ -5310,7 +5509,6 @@ static void intel_init_display(struct drm_device *dev)
 void intel_modeset_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int num_pipe;
        int i;
 
        drm_mode_config_init(dev);
@@ -5340,13 +5538,13 @@ void intel_modeset_init(struct drm_device *dev)
                dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0);
 
        if (IS_MOBILE(dev) || IS_I9XX(dev))
-               num_pipe = 2;
+               dev_priv->num_pipe = 2;
        else
-               num_pipe = 1;
+               dev_priv->num_pipe = 1;
        DRM_DEBUG_KMS("%d display pipe%s available.\n",
-                 num_pipe, num_pipe > 1 ? "s" : "");
+                     dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : "");
 
-       for (i = 0; i < num_pipe; i++) {
+       for (i = 0; i < dev_priv->num_pipe; i++) {
                intel_crtc_init(dev, i);
        }
 
@@ -5354,8 +5552,10 @@ void intel_modeset_init(struct drm_device *dev)
 
        intel_init_clock_gating(dev);
 
-       if (IS_IRONLAKE_M(dev))
+       if (IS_IRONLAKE_M(dev)) {
                ironlake_enable_drps(dev);
+               intel_init_emon(dev);
+       }
 
        INIT_WORK(&dev_priv->idle_work, intel_idle_update);
        setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
index 6b1c9a27c27a236aada13d0ddf257f7a8330047c..1aac59e83bff0c45a0da94e1f083d40d9e30b396 100644 (file)
@@ -135,6 +135,12 @@ intel_dp_link_required(struct drm_device *dev,
                return pixel_clock * 3;
 }
 
+static int
+intel_dp_max_data_rate(int max_link_clock, int max_lanes)
+{
+       return (max_link_clock * max_lanes * 8) / 10;
+}
+
 static int
 intel_dp_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
@@ -144,8 +150,11 @@ intel_dp_mode_valid(struct drm_connector *connector,
        int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder));
        int max_lanes = intel_dp_max_lane_count(intel_encoder);
 
-       if (intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
-                       > max_link_clock * max_lanes)
+       /* only refuse the mode on non eDP since we have seen some wierd eDP panels
+          which are outside spec tolerances but somehow work by magic */
+       if (!IS_eDP(intel_encoder) &&
+           (intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
+            > intel_dp_max_data_rate(max_link_clock, max_lanes)))
                return MODE_CLOCK_HIGH;
 
        if (mode->clock < 10000)
@@ -506,7 +515,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
 
        for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
                for (clock = 0; clock <= max_clock; clock++) {
-                       int link_avail = intel_dp_link_clock(bws[clock]) * lane_count;
+                       int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
 
                        if (intel_dp_link_required(encoder->dev, intel_encoder, mode->clock)
                                        <= link_avail) {
@@ -521,6 +530,18 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                        }
                }
        }
+
+       if (IS_eDP(intel_encoder)) {
+               /* okay we failed just pick the highest */
+               dp_priv->lane_count = max_lane_count;
+               dp_priv->link_bw = bws[max_clock];
+               adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
+               DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
+                             "count %d clock %d\n",
+                             dp_priv->link_bw, dp_priv->lane_count,
+                             adjusted_mode->clock);
+               return true;
+       }
        return false;
 }
 
@@ -576,7 +597,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
                struct intel_encoder *intel_encoder;
                struct intel_dp_priv *dp_priv;
 
-               if (!encoder || encoder->crtc != crtc)
+               if (encoder->crtc != crtc)
                        continue;
 
                intel_encoder = enc_to_intel_encoder(encoder);
@@ -675,10 +696,9 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
        dp_priv->link_configuration[1] = dp_priv->lane_count;
 
        /*
-        * Check for DPCD version > 1.1,
-        * enable enahanced frame stuff in that case
+        * Check for DPCD version > 1.1 and enhanced framing support
         */
-       if (dp_priv->dpcd[0] >= 0x11) {
+       if (dp_priv->dpcd[0] >= 0x11 && (dp_priv->dpcd[2] & DP_ENHANCED_FRAME_CAP)) {
                dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
                dp_priv->DP |= DP_ENHANCED_FRAMING;
        }
@@ -1208,6 +1228,8 @@ ironlake_dp_detect(struct drm_connector *connector)
                if (dp_priv->dpcd[0] != 0)
                        status = connector_status_connected;
        }
+       DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", dp_priv->dpcd[0],
+                     dp_priv->dpcd[1], dp_priv->dpcd[2], dp_priv->dpcd[3]);
        return status;
 }
 
@@ -1352,7 +1374,7 @@ intel_trans_dp_port_sel (struct drm_crtc *crtc)
        struct intel_encoder *intel_encoder = NULL;
 
        list_for_each_entry(encoder, &mode_config->encoder_list, head) {
-               if (!encoder || encoder->crtc != crtc)
+               if (encoder->crtc != crtc)
                        continue;
 
                intel_encoder = enc_to_intel_encoder(encoder);
index df931f7876652e7af0b8f6f480fdbd05ce3596ae..72206f37c4fb847c8d32d80c5c893fd3a68a5faa 100644 (file)
@@ -224,6 +224,7 @@ extern void intel_fbdev_fini(struct drm_device *dev);
 
 extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
 extern void intel_finish_page_flip(struct drm_device *dev, int pipe);
+extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
 
 extern void intel_setup_overlay(struct drm_device *dev);
 extern void intel_cleanup_overlay(struct drm_device *dev);
index 6f53cf7fbc506a4fe5fac3d7b726001f083bd37b..c3c505244e07367c3a8a3cb17698d60ef5ce5407 100644 (file)
@@ -105,7 +105,11 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
        }
 
        /* Flush everything out, we'll be doing GTT only from now on */
-       i915_gem_object_set_to_gtt_domain(fbo, 1);
+       ret = i915_gem_object_set_to_gtt_domain(fbo, 1);
+       if (ret) {
+               DRM_ERROR("failed to bind fb: %d.\n", ret);
+               goto out_unpin;
+       }
 
        info = framebuffer_alloc(0, device);
        if (!info) {
@@ -241,6 +245,7 @@ int intel_fbdev_init(struct drm_device *dev)
 {
        struct intel_fbdev *ifbdev;
        drm_i915_private_t *dev_priv = dev->dev_private;
+       int ret;
 
        ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
        if (!ifbdev)
@@ -249,8 +254,13 @@ int intel_fbdev_init(struct drm_device *dev)
        dev_priv->fbdev = ifbdev;
        ifbdev->helper.funcs = &intel_fb_helper_funcs;
 
-       drm_fb_helper_init(dev, &ifbdev->helper, 2,
-                          INTELFB_CONN_LIMIT);
+       ret = drm_fb_helper_init(dev, &ifbdev->helper,
+                                dev_priv->num_pipe,
+                                INTELFB_CONN_LIMIT);
+       if (ret) {
+               kfree(ifbdev);
+               return ret;
+       }
 
        drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
        drm_fb_helper_initial_config(&ifbdev->helper, 32);
index 65727f0a79a3440202e5f315762431d975b5a9cf..83bd764b000e51cff80ac0a79a14b8cc5f05fcb4 100644 (file)
@@ -59,8 +59,11 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
                SDVO_VSYNC_ACTIVE_HIGH |
                SDVO_HSYNC_ACTIVE_HIGH;
 
-       if (hdmi_priv->has_hdmi_sink)
+       if (hdmi_priv->has_hdmi_sink) {
                sdvox |= SDVO_AUDIO_ENABLE;
+               if (HAS_PCH_CPT(dev))
+                       sdvox |= HDMI_MODE_SELECT;
+       }
 
        if (intel_crtc->pipe == 1) {
                if (HAS_PCH_CPT(dev))
index 6a1accd83aecd9171f719deca33a04e078534585..31df55f0a0a7950a0e59ebce556fc30cde35b891 100644 (file)
@@ -983,8 +983,8 @@ void intel_lvds_init(struct drm_device *dev)
 
        drm_connector_attach_property(&intel_connector->base,
                                      dev->mode_config.scaling_mode_property,
-                                     DRM_MODE_SCALE_FULLSCREEN);
-       lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN;
+                                     DRM_MODE_SCALE_ASPECT);
+       lvds_priv->fitting_mode = DRM_MODE_SCALE_ASPECT;
        /*
         * LVDS discovery:
         * 1) check for EDID on DDC
index b0e17b06eb6ea08c2c67e57e8b62fe6989cd4e2d..d7ad5139d17cefa543ae30652757b81ff48b407b 100644 (file)
@@ -211,9 +211,8 @@ static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
 static int intel_overlay_on(struct intel_overlay *overlay)
 {
        struct drm_device *dev = overlay->dev;
-        drm_i915_private_t *dev_priv = dev->dev_private;
        int ret;
-       RING_LOCALS;
+       drm_i915_private_t *dev_priv = dev->dev_private;
 
        BUG_ON(overlay->active);
 
@@ -227,11 +226,13 @@ static int intel_overlay_on(struct intel_overlay *overlay)
        OUT_RING(MI_NOOP);
        ADVANCE_LP_RING();
 
-       overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+       overlay->last_flip_req =
+               i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
        if (overlay->last_flip_req == 0)
                return -ENOMEM;
 
-       ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+       ret = i915_do_wait_request(dev,
+                       overlay->last_flip_req, 1, &dev_priv->render_ring);
        if (ret != 0)
                return ret;
 
@@ -248,7 +249,6 @@ static void intel_overlay_continue(struct intel_overlay *overlay,
         drm_i915_private_t *dev_priv = dev->dev_private;
        u32 flip_addr = overlay->flip_addr;
        u32 tmp;
-       RING_LOCALS;
 
        BUG_ON(!overlay->active);
 
@@ -265,7 +265,8 @@ static void intel_overlay_continue(struct intel_overlay *overlay,
        OUT_RING(flip_addr);
         ADVANCE_LP_RING();
 
-       overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+       overlay->last_flip_req =
+               i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
 }
 
 static int intel_overlay_wait_flip(struct intel_overlay *overlay)
@@ -274,10 +275,10 @@ static int intel_overlay_wait_flip(struct intel_overlay *overlay)
         drm_i915_private_t *dev_priv = dev->dev_private;
        int ret;
        u32 tmp;
-       RING_LOCALS;
 
        if (overlay->last_flip_req != 0) {
-               ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+               ret = i915_do_wait_request(dev, overlay->last_flip_req,
+                               1, &dev_priv->render_ring);
                if (ret == 0) {
                        overlay->last_flip_req = 0;
 
@@ -296,11 +297,13 @@ static int intel_overlay_wait_flip(struct intel_overlay *overlay)
         OUT_RING(MI_NOOP);
         ADVANCE_LP_RING();
 
-       overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+       overlay->last_flip_req =
+               i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
        if (overlay->last_flip_req == 0)
                return -ENOMEM;
 
-       ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+       ret = i915_do_wait_request(dev, overlay->last_flip_req,
+                       1, &dev_priv->render_ring);
        if (ret != 0)
                return ret;
 
@@ -314,9 +317,8 @@ static int intel_overlay_off(struct intel_overlay *overlay)
 {
        u32 flip_addr = overlay->flip_addr;
        struct drm_device *dev = overlay->dev;
-        drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_private_t *dev_priv = dev->dev_private;
        int ret;
-       RING_LOCALS;
 
        BUG_ON(!overlay->active);
 
@@ -336,11 +338,13 @@ static int intel_overlay_off(struct intel_overlay *overlay)
         OUT_RING(MI_NOOP);
         ADVANCE_LP_RING();
 
-       overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+       overlay->last_flip_req =
+               i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
        if (overlay->last_flip_req == 0)
                return -ENOMEM;
 
-       ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+       ret = i915_do_wait_request(dev, overlay->last_flip_req,
+                       1, &dev_priv->render_ring);
        if (ret != 0)
                return ret;
 
@@ -354,11 +358,13 @@ static int intel_overlay_off(struct intel_overlay *overlay)
         OUT_RING(MI_NOOP);
        ADVANCE_LP_RING();
 
-       overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+       overlay->last_flip_req =
+               i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
        if (overlay->last_flip_req == 0)
                return -ENOMEM;
 
-       ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+       ret = i915_do_wait_request(dev, overlay->last_flip_req,
+                       1, &dev_priv->render_ring);
        if (ret != 0)
                return ret;
 
@@ -390,22 +396,23 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
                                         int interruptible)
 {
        struct drm_device *dev = overlay->dev;
-        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_gem_object *obj;
+       drm_i915_private_t *dev_priv = dev->dev_private;
        u32 flip_addr;
        int ret;
-       RING_LOCALS;
 
        if (overlay->hw_wedged == HW_WEDGED)
                return -EIO;
 
        if (overlay->last_flip_req == 0) {
-               overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+               overlay->last_flip_req =
+                       i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
                if (overlay->last_flip_req == 0)
                        return -ENOMEM;
        }
 
-       ret = i915_do_wait_request(dev, overlay->last_flip_req, interruptible);
+       ret = i915_do_wait_request(dev, overlay->last_flip_req,
+                       interruptible, &dev_priv->render_ring);
        if (ret != 0)
                return ret;
 
@@ -429,12 +436,13 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
                        OUT_RING(MI_NOOP);
                        ADVANCE_LP_RING();
 
-                       overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+                       overlay->last_flip_req = i915_add_request(dev, NULL,
+                                       0, &dev_priv->render_ring);
                        if (overlay->last_flip_req == 0)
                                return -ENOMEM;
 
                        ret = i915_do_wait_request(dev, overlay->last_flip_req,
-                                       interruptible);
+                                       interruptible, &dev_priv->render_ring);
                        if (ret != 0)
                                return ret;
 
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
new file mode 100644 (file)
index 0000000..26362f8
--- /dev/null
@@ -0,0 +1,851 @@
+/*
+ * Copyright Â© 2008-2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *    Zou Nan hai <nanhai.zou@intel.com>
+ *    Xiang Hai hao<haihao.xiang@intel.com>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drv.h"
+#include "i915_drm.h"
+#include "i915_trace.h"
+
+static void
+render_ring_flush(struct drm_device *dev,
+               struct intel_ring_buffer *ring,
+               u32     invalidate_domains,
+               u32     flush_domains)
+{
+#if WATCH_EXEC
+       DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
+                 invalidate_domains, flush_domains);
+#endif
+       u32 cmd;
+       trace_i915_gem_request_flush(dev, ring->next_seqno,
+                                    invalidate_domains, flush_domains);
+
+       if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) {
+               /*
+                * read/write caches:
+                *
+                * I915_GEM_DOMAIN_RENDER is always invalidated, but is
+                * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
+                * also flushed at 2d versus 3d pipeline switches.
+                *
+                * read-only caches:
+                *
+                * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
+                * MI_READ_FLUSH is set, and is always flushed on 965.
+                *
+                * I915_GEM_DOMAIN_COMMAND may not exist?
+                *
+                * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
+                * invalidated when MI_EXE_FLUSH is set.
+                *
+                * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
+                * invalidated with every MI_FLUSH.
+                *
+                * TLBs:
+                *
+                * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
+                * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
+                * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
+                * are flushed at any MI_FLUSH.
+                */
+
+               cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
+               if ((invalidate_domains|flush_domains) &
+                   I915_GEM_DOMAIN_RENDER)
+                       cmd &= ~MI_NO_WRITE_FLUSH;
+               if (!IS_I965G(dev)) {
+                       /*
+                        * On the 965, the sampler cache always gets flushed
+                        * and this bit is reserved.
+                        */
+                       if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
+                               cmd |= MI_READ_FLUSH;
+               }
+               if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
+                       cmd |= MI_EXE_FLUSH;
+
+#if WATCH_EXEC
+               DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
+#endif
+               intel_ring_begin(dev, ring, 2);
+               intel_ring_emit(dev, ring, cmd);
+               intel_ring_emit(dev, ring, MI_NOOP);
+               intel_ring_advance(dev, ring);
+       }
+}
+
+static unsigned int render_ring_get_head(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       return I915_READ(PRB0_HEAD) & HEAD_ADDR;
+}
+
+static unsigned int render_ring_get_tail(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       return I915_READ(PRB0_TAIL) & TAIL_ADDR;
+}
+
+static unsigned int render_ring_get_active_head(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
+
+       return I915_READ(acthd_reg);
+}
+
+static void render_ring_advance_ring(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       I915_WRITE(PRB0_TAIL, ring->tail);
+}
+
+static int init_ring_common(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       u32 head;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_gem_object *obj_priv;
+       obj_priv = to_intel_bo(ring->gem_object);
+
+       /* Stop the ring if it's running. */
+       I915_WRITE(ring->regs.ctl, 0);
+       I915_WRITE(ring->regs.head, 0);
+       I915_WRITE(ring->regs.tail, 0);
+
+       /* Initialize the ring. */
+       I915_WRITE(ring->regs.start, obj_priv->gtt_offset);
+       head = ring->get_head(dev, ring);
+
+       /* G45 ring initialization fails to reset head to zero */
+       if (head != 0) {
+               DRM_ERROR("%s head not reset to zero "
+                               "ctl %08x head %08x tail %08x start %08x\n",
+                               ring->name,
+                               I915_READ(ring->regs.ctl),
+                               I915_READ(ring->regs.head),
+                               I915_READ(ring->regs.tail),
+                               I915_READ(ring->regs.start));
+
+               I915_WRITE(ring->regs.head, 0);
+
+               DRM_ERROR("%s head forced to zero "
+                               "ctl %08x head %08x tail %08x start %08x\n",
+                               ring->name,
+                               I915_READ(ring->regs.ctl),
+                               I915_READ(ring->regs.head),
+                               I915_READ(ring->regs.tail),
+                               I915_READ(ring->regs.start));
+       }
+
+       I915_WRITE(ring->regs.ctl,
+                       ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES)
+                       | RING_NO_REPORT | RING_VALID);
+
+       head = I915_READ(ring->regs.head) & HEAD_ADDR;
+       /* If the head is still not zero, the ring is dead */
+       if (head != 0) {
+               DRM_ERROR("%s initialization failed "
+                               "ctl %08x head %08x tail %08x start %08x\n",
+                               ring->name,
+                               I915_READ(ring->regs.ctl),
+                               I915_READ(ring->regs.head),
+                               I915_READ(ring->regs.tail),
+                               I915_READ(ring->regs.start));
+               return -EIO;
+       }
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               i915_kernel_lost_context(dev);
+       else {
+               ring->head = ring->get_head(dev, ring);
+               ring->tail = ring->get_tail(dev, ring);
+               ring->space = ring->head - (ring->tail + 8);
+               if (ring->space < 0)
+                       ring->space += ring->size;
+       }
+       return 0;
+}
+
+static int init_render_ring(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       int ret = init_ring_common(dev, ring);
+       if (IS_I9XX(dev) && !IS_GEN3(dev)) {
+               I915_WRITE(MI_MODE,
+                               (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH);
+       }
+       return ret;
+}
+
+#define PIPE_CONTROL_FLUSH(addr)                                       \
+do {                                                                   \
+       OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |          \
+                PIPE_CONTROL_DEPTH_STALL | 2);                         \
+       OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT);                       \
+       OUT_RING(0);                                                    \
+       OUT_RING(0);                                                    \
+} while (0)
+
+/**
+ * Creates a new sequence number, emitting a write of it to the status page
+ * plus an interrupt, which will trigger i915_user_interrupt_handler.
+ *
+ * Must be called with struct_lock held.
+ *
+ * Returned sequence numbers are nonzero on success.
+ */
+static u32
+render_ring_add_request(struct drm_device *dev,
+               struct intel_ring_buffer *ring,
+               struct drm_file *file_priv,
+               u32 flush_domains)
+{
+       u32 seqno;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       seqno = intel_ring_get_seqno(dev, ring);
+
+       if (IS_GEN6(dev)) {
+               BEGIN_LP_RING(6);
+               OUT_RING(GFX_OP_PIPE_CONTROL | 3);
+               OUT_RING(PIPE_CONTROL_QW_WRITE |
+                        PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_IS_FLUSH |
+                        PIPE_CONTROL_NOTIFY);
+               OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+               OUT_RING(seqno);
+               OUT_RING(0);
+               OUT_RING(0);
+               ADVANCE_LP_RING();
+       } else if (HAS_PIPE_CONTROL(dev)) {
+               u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
+
+               /*
+                * Workaround qword write incoherence by flushing the
+                * PIPE_NOTIFY buffers out to memory before requesting
+                * an interrupt.
+                */
+               BEGIN_LP_RING(32);
+               OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+                        PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
+               OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+               OUT_RING(seqno);
+               OUT_RING(0);
+               PIPE_CONTROL_FLUSH(scratch_addr);
+               scratch_addr += 128; /* write to separate cachelines */
+               PIPE_CONTROL_FLUSH(scratch_addr);
+               scratch_addr += 128;
+               PIPE_CONTROL_FLUSH(scratch_addr);
+               scratch_addr += 128;
+               PIPE_CONTROL_FLUSH(scratch_addr);
+               scratch_addr += 128;
+               PIPE_CONTROL_FLUSH(scratch_addr);
+               scratch_addr += 128;
+               PIPE_CONTROL_FLUSH(scratch_addr);
+               OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+                        PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
+                        PIPE_CONTROL_NOTIFY);
+               OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+               OUT_RING(seqno);
+               OUT_RING(0);
+               ADVANCE_LP_RING();
+       } else {
+               BEGIN_LP_RING(4);
+               OUT_RING(MI_STORE_DWORD_INDEX);
+               OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+               OUT_RING(seqno);
+
+               OUT_RING(MI_USER_INTERRUPT);
+               ADVANCE_LP_RING();
+       }
+       return seqno;
+}
+
+static u32
+render_ring_get_gem_seqno(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       if (HAS_PIPE_CONTROL(dev))
+               return ((volatile u32 *)(dev_priv->seqno_page))[0];
+       else
+               return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
+static void
+render_ring_get_user_irq(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+       if (dev->irq_enabled && (++ring->user_irq_refcount == 1)) {
+               if (HAS_PCH_SPLIT(dev))
+                       ironlake_enable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
+               else
+                       i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
+       }
+       spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+}
+
+static void
+render_ring_put_user_irq(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+       BUG_ON(dev->irq_enabled && ring->user_irq_refcount <= 0);
+       if (dev->irq_enabled && (--ring->user_irq_refcount == 0)) {
+               if (HAS_PCH_SPLIT(dev))
+                       ironlake_disable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
+               else
+                       i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
+       }
+       spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+}
+
+static void render_setup_status_page(struct drm_device *dev,
+       struct  intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       if (IS_GEN6(dev)) {
+               I915_WRITE(HWS_PGA_GEN6, ring->status_page.gfx_addr);
+               I915_READ(HWS_PGA_GEN6); /* posting read */
+       } else {
+               I915_WRITE(HWS_PGA, ring->status_page.gfx_addr);
+               I915_READ(HWS_PGA); /* posting read */
+       }
+
+}
+
+void
+bsd_ring_flush(struct drm_device *dev,
+               struct intel_ring_buffer *ring,
+               u32     invalidate_domains,
+               u32     flush_domains)
+{
+       intel_ring_begin(dev, ring, 2);
+       intel_ring_emit(dev, ring, MI_FLUSH);
+       intel_ring_emit(dev, ring, MI_NOOP);
+       intel_ring_advance(dev, ring);
+}
+
+static inline unsigned int bsd_ring_get_head(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       return I915_READ(BSD_RING_HEAD) & HEAD_ADDR;
+}
+
+static inline unsigned int bsd_ring_get_tail(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       return I915_READ(BSD_RING_TAIL) & TAIL_ADDR;
+}
+
+static inline unsigned int bsd_ring_get_active_head(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       return I915_READ(BSD_RING_ACTHD);
+}
+
+static inline void bsd_ring_advance_ring(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       I915_WRITE(BSD_RING_TAIL, ring->tail);
+}
+
+static int init_bsd_ring(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       return init_ring_common(dev, ring);
+}
+
+static u32
+bsd_ring_add_request(struct drm_device *dev,
+               struct intel_ring_buffer *ring,
+               struct drm_file *file_priv,
+               u32 flush_domains)
+{
+       u32 seqno;
+       seqno = intel_ring_get_seqno(dev, ring);
+       intel_ring_begin(dev, ring, 4);
+       intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX);
+       intel_ring_emit(dev, ring,
+                       I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+       intel_ring_emit(dev, ring, seqno);
+       intel_ring_emit(dev, ring, MI_USER_INTERRUPT);
+       intel_ring_advance(dev, ring);
+
+       DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno);
+
+       return seqno;
+}
+
+static void bsd_setup_status_page(struct drm_device *dev,
+               struct  intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       I915_WRITE(BSD_HWS_PGA, ring->status_page.gfx_addr);
+       I915_READ(BSD_HWS_PGA);
+}
+
+static void
+bsd_ring_get_user_irq(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       /* do nothing */
+}
+static void
+bsd_ring_put_user_irq(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       /* do nothing */
+}
+
+static u32
+bsd_ring_get_gem_seqno(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
+static int
+bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev,
+               struct intel_ring_buffer *ring,
+               struct drm_i915_gem_execbuffer2 *exec,
+               struct drm_clip_rect *cliprects,
+               uint64_t exec_offset)
+{
+       uint32_t exec_start;
+       exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
+       intel_ring_begin(dev, ring, 2);
+       intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START |
+                       (2 << 6) | MI_BATCH_NON_SECURE_I965);
+       intel_ring_emit(dev, ring, exec_start);
+       intel_ring_advance(dev, ring);
+       return 0;
+}
+
+
+static int
+render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
+               struct intel_ring_buffer *ring,
+               struct drm_i915_gem_execbuffer2 *exec,
+               struct drm_clip_rect *cliprects,
+               uint64_t exec_offset)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       int nbox = exec->num_cliprects;
+       int i = 0, count;
+       uint32_t exec_start, exec_len;
+       exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
+       exec_len = (uint32_t) exec->batch_len;
+
+       trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1);
+
+       count = nbox ? nbox : 1;
+
+       for (i = 0; i < count; i++) {
+               if (i < nbox) {
+                       int ret = i915_emit_box(dev, cliprects, i,
+                                               exec->DR1, exec->DR4);
+                       if (ret)
+                               return ret;
+               }
+
+               if (IS_I830(dev) || IS_845G(dev)) {
+                       intel_ring_begin(dev, ring, 4);
+                       intel_ring_emit(dev, ring, MI_BATCH_BUFFER);
+                       intel_ring_emit(dev, ring,
+                                       exec_start | MI_BATCH_NON_SECURE);
+                       intel_ring_emit(dev, ring, exec_start + exec_len - 4);
+                       intel_ring_emit(dev, ring, 0);
+               } else {
+                       intel_ring_begin(dev, ring, 4);
+                       if (IS_I965G(dev)) {
+                               intel_ring_emit(dev, ring,
+                                               MI_BATCH_BUFFER_START | (2 << 6)
+                                               | MI_BATCH_NON_SECURE_I965);
+                               intel_ring_emit(dev, ring, exec_start);
+                       } else {
+                               intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START
+                                               | (2 << 6));
+                               intel_ring_emit(dev, ring, exec_start |
+                                               MI_BATCH_NON_SECURE);
+                       }
+               }
+               intel_ring_advance(dev, ring);
+       }
+
+       /* XXX breadcrumb */
+       return 0;
+}
+
+static void cleanup_status_page(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_gem_object *obj;
+       struct drm_i915_gem_object *obj_priv;
+
+       obj = ring->status_page.obj;
+       if (obj == NULL)
+               return;
+       obj_priv = to_intel_bo(obj);
+
+       kunmap(obj_priv->pages[0]);
+       i915_gem_object_unpin(obj);
+       drm_gem_object_unreference(obj);
+       ring->status_page.obj = NULL;
+
+       memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+}
+
+static int init_status_page(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_gem_object *obj;
+       struct drm_i915_gem_object *obj_priv;
+       int ret;
+
+       obj = i915_gem_alloc_object(dev, 4096);
+       if (obj == NULL) {
+               DRM_ERROR("Failed to allocate status page\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+       obj_priv = to_intel_bo(obj);
+       obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
+
+       ret = i915_gem_object_pin(obj, 4096);
+       if (ret != 0) {
+               goto err_unref;
+       }
+
+       ring->status_page.gfx_addr = obj_priv->gtt_offset;
+       ring->status_page.page_addr = kmap(obj_priv->pages[0]);
+       if (ring->status_page.page_addr == NULL) {
+               memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+               goto err_unpin;
+       }
+       ring->status_page.obj = obj;
+       memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+
+       ring->setup_status_page(dev, ring);
+       DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
+                       ring->name, ring->status_page.gfx_addr);
+
+       return 0;
+
+err_unpin:
+       i915_gem_object_unpin(obj);
+err_unref:
+       drm_gem_object_unreference(obj);
+err:
+       return ret;
+}
+
+
+int intel_init_ring_buffer(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       int ret;
+       struct drm_i915_gem_object *obj_priv;
+       struct drm_gem_object *obj;
+       ring->dev = dev;
+
+       if (I915_NEED_GFX_HWS(dev)) {
+               ret = init_status_page(dev, ring);
+               if (ret)
+                       return ret;
+       }
+
+       obj = i915_gem_alloc_object(dev, ring->size);
+       if (obj == NULL) {
+               DRM_ERROR("Failed to allocate ringbuffer\n");
+               ret = -ENOMEM;
+               goto cleanup;
+       }
+
+       ring->gem_object = obj;
+
+       ret = i915_gem_object_pin(obj, ring->alignment);
+       if (ret != 0) {
+               drm_gem_object_unreference(obj);
+               goto cleanup;
+       }
+
+       obj_priv = to_intel_bo(obj);
+       ring->map.size = ring->size;
+       ring->map.offset = dev->agp->base + obj_priv->gtt_offset;
+       ring->map.type = 0;
+       ring->map.flags = 0;
+       ring->map.mtrr = 0;
+
+       drm_core_ioremap_wc(&ring->map, dev);
+       if (ring->map.handle == NULL) {
+               DRM_ERROR("Failed to map ringbuffer.\n");
+               i915_gem_object_unpin(obj);
+               drm_gem_object_unreference(obj);
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       ring->virtual_start = ring->map.handle;
+       ret = ring->init(dev, ring);
+       if (ret != 0) {
+               intel_cleanup_ring_buffer(dev, ring);
+               return ret;
+       }
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               i915_kernel_lost_context(dev);
+       else {
+               ring->head = ring->get_head(dev, ring);
+               ring->tail = ring->get_tail(dev, ring);
+               ring->space = ring->head - (ring->tail + 8);
+               if (ring->space < 0)
+                       ring->space += ring->size;
+       }
+       INIT_LIST_HEAD(&ring->active_list);
+       INIT_LIST_HEAD(&ring->request_list);
+       return ret;
+cleanup:
+       cleanup_status_page(dev, ring);
+       return ret;
+}
+
+void intel_cleanup_ring_buffer(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       if (ring->gem_object == NULL)
+               return;
+
+       drm_core_ioremapfree(&ring->map, dev);
+
+       i915_gem_object_unpin(ring->gem_object);
+       drm_gem_object_unreference(ring->gem_object);
+       ring->gem_object = NULL;
+       cleanup_status_page(dev, ring);
+}
+
+int intel_wrap_ring_buffer(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       unsigned int *virt;
+       int rem;
+       rem = ring->size - ring->tail;
+
+       if (ring->space < rem) {
+               int ret = intel_wait_ring_buffer(dev, ring, rem);
+               if (ret)
+                       return ret;
+       }
+
+       virt = (unsigned int *)(ring->virtual_start + ring->tail);
+       rem /= 4;
+       while (rem--)
+               *virt++ = MI_NOOP;
+
+       ring->tail = 0;
+       ring->space = ring->head - 8;
+
+       return 0;
+}
+
+int intel_wait_ring_buffer(struct drm_device *dev,
+               struct intel_ring_buffer *ring, int n)
+{
+       unsigned long end;
+
+       trace_i915_ring_wait_begin (dev);
+       end = jiffies + 3 * HZ;
+       do {
+               ring->head = ring->get_head(dev, ring);
+               ring->space = ring->head - (ring->tail + 8);
+               if (ring->space < 0)
+                       ring->space += ring->size;
+               if (ring->space >= n) {
+                       trace_i915_ring_wait_end (dev);
+                       return 0;
+               }
+
+               if (dev->primary->master) {
+                       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
+                       if (master_priv->sarea_priv)
+                               master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+               }
+
+               yield();
+       } while (!time_after(jiffies, end));
+       trace_i915_ring_wait_end (dev);
+       return -EBUSY;
+}
+
+void intel_ring_begin(struct drm_device *dev,
+               struct intel_ring_buffer *ring, int num_dwords)
+{
+       int n = 4*num_dwords;
+       if (unlikely(ring->tail + n > ring->size))
+               intel_wrap_ring_buffer(dev, ring);
+       if (unlikely(ring->space < n))
+               intel_wait_ring_buffer(dev, ring, n);
+}
+
+void intel_ring_emit(struct drm_device *dev,
+               struct intel_ring_buffer *ring, unsigned int data)
+{
+       unsigned int *virt = ring->virtual_start + ring->tail;
+       *virt = data;
+       ring->tail += 4;
+       ring->tail &= ring->size - 1;
+       ring->space -= 4;
+}
+
+void intel_ring_advance(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       ring->advance_ring(dev, ring);
+}
+
+void intel_fill_struct(struct drm_device *dev,
+               struct intel_ring_buffer *ring,
+               void *data,
+               unsigned int len)
+{
+       unsigned int *virt = ring->virtual_start + ring->tail;
+       BUG_ON((len&~(4-1)) != 0);
+       intel_ring_begin(dev, ring, len/4);
+       memcpy(virt, data, len);
+       ring->tail += len;
+       ring->tail &= ring->size - 1;
+       ring->space -= len;
+       intel_ring_advance(dev, ring);
+}
+
+u32 intel_ring_get_seqno(struct drm_device *dev,
+               struct intel_ring_buffer *ring)
+{
+       u32 seqno;
+       seqno = ring->next_seqno;
+
+       /* reserve 0 for non-seqno */
+       if (++ring->next_seqno == 0)
+               ring->next_seqno = 1;
+       return seqno;
+}
+
+struct intel_ring_buffer render_ring = {
+       .name                   = "render ring",
+       .regs                   = {
+               .ctl = PRB0_CTL,
+               .head = PRB0_HEAD,
+               .tail = PRB0_TAIL,
+               .start = PRB0_START
+       },
+       .ring_flag              = I915_EXEC_RENDER,
+       .size                   = 32 * PAGE_SIZE,
+       .alignment              = PAGE_SIZE,
+       .virtual_start          = NULL,
+       .dev                    = NULL,
+       .gem_object             = NULL,
+       .head                   = 0,
+       .tail                   = 0,
+       .space                  = 0,
+       .next_seqno             = 1,
+       .user_irq_refcount      = 0,
+       .irq_gem_seqno          = 0,
+       .waiting_gem_seqno      = 0,
+       .setup_status_page      = render_setup_status_page,
+       .init                   = init_render_ring,
+       .get_head               = render_ring_get_head,
+       .get_tail               = render_ring_get_tail,
+       .get_active_head        = render_ring_get_active_head,
+       .advance_ring           = render_ring_advance_ring,
+       .flush                  = render_ring_flush,
+       .add_request            = render_ring_add_request,
+       .get_gem_seqno          = render_ring_get_gem_seqno,
+       .user_irq_get           = render_ring_get_user_irq,
+       .user_irq_put           = render_ring_put_user_irq,
+       .dispatch_gem_execbuffer = render_ring_dispatch_gem_execbuffer,
+       .status_page            = {NULL, 0, NULL},
+       .map                    = {0,}
+};
+
+/* ring buffer for bit-stream decoder */
+
+struct intel_ring_buffer bsd_ring = {
+       .name                   = "bsd ring",
+       .regs                   = {
+               .ctl = BSD_RING_CTL,
+               .head = BSD_RING_HEAD,
+               .tail = BSD_RING_TAIL,
+               .start = BSD_RING_START
+       },
+       .ring_flag              = I915_EXEC_BSD,
+       .size                   = 32 * PAGE_SIZE,
+       .alignment              = PAGE_SIZE,
+       .virtual_start          = NULL,
+       .dev                    = NULL,
+       .gem_object             = NULL,
+       .head                   = 0,
+       .tail                   = 0,
+       .space                  = 0,
+       .next_seqno             = 1,
+       .user_irq_refcount      = 0,
+       .irq_gem_seqno          = 0,
+       .waiting_gem_seqno      = 0,
+       .setup_status_page      = bsd_setup_status_page,
+       .init                   = init_bsd_ring,
+       .get_head               = bsd_ring_get_head,
+       .get_tail               = bsd_ring_get_tail,
+       .get_active_head        = bsd_ring_get_active_head,
+       .advance_ring           = bsd_ring_advance_ring,
+       .flush                  = bsd_ring_flush,
+       .add_request            = bsd_ring_add_request,
+       .get_gem_seqno          = bsd_ring_get_gem_seqno,
+       .user_irq_get           = bsd_ring_get_user_irq,
+       .user_irq_put           = bsd_ring_put_user_irq,
+       .dispatch_gem_execbuffer = bsd_ring_dispatch_gem_execbuffer,
+       .status_page            = {NULL, 0, NULL},
+       .map                    = {0,}
+};
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
new file mode 100644 (file)
index 0000000..d5568d3
--- /dev/null
@@ -0,0 +1,124 @@
+#ifndef _INTEL_RINGBUFFER_H_
+#define _INTEL_RINGBUFFER_H_
+
+struct  intel_hw_status_page {
+       void            *page_addr;
+       unsigned int    gfx_addr;
+       struct          drm_gem_object *obj;
+};
+
+struct drm_i915_gem_execbuffer2;
+struct  intel_ring_buffer {
+       const char      *name;
+       struct          ring_regs {
+                       u32 ctl;
+                       u32 head;
+                       u32 tail;
+                       u32 start;
+       } regs;
+       unsigned int    ring_flag;
+       unsigned long   size;
+       unsigned int    alignment;
+       void            *virtual_start;
+       struct          drm_device *dev;
+       struct          drm_gem_object *gem_object;
+
+       unsigned int    head;
+       unsigned int    tail;
+       unsigned int    space;
+       u32             next_seqno;
+       struct intel_hw_status_page status_page;
+
+       u32             irq_gem_seqno;          /* last seq seem at irq time */
+       u32             waiting_gem_seqno;
+       int             user_irq_refcount;
+       void            (*user_irq_get)(struct drm_device *dev,
+                       struct intel_ring_buffer *ring);
+       void            (*user_irq_put)(struct drm_device *dev,
+                       struct intel_ring_buffer *ring);
+       void            (*setup_status_page)(struct drm_device *dev,
+                       struct  intel_ring_buffer *ring);
+
+       int             (*init)(struct drm_device *dev,
+                       struct intel_ring_buffer *ring);
+
+       unsigned int    (*get_head)(struct drm_device *dev,
+                       struct intel_ring_buffer *ring);
+       unsigned int    (*get_tail)(struct drm_device *dev,
+                       struct intel_ring_buffer *ring);
+       unsigned int    (*get_active_head)(struct drm_device *dev,
+                       struct intel_ring_buffer *ring);
+       void            (*advance_ring)(struct drm_device *dev,
+                       struct intel_ring_buffer *ring);
+       void            (*flush)(struct drm_device *dev,
+                       struct intel_ring_buffer *ring,
+                       u32     invalidate_domains,
+                       u32     flush_domains);
+       u32             (*add_request)(struct drm_device *dev,
+                       struct intel_ring_buffer *ring,
+                       struct drm_file *file_priv,
+                       u32 flush_domains);
+       u32             (*get_gem_seqno)(struct drm_device *dev,
+                       struct intel_ring_buffer *ring);
+       int             (*dispatch_gem_execbuffer)(struct drm_device *dev,
+                       struct intel_ring_buffer *ring,
+                       struct drm_i915_gem_execbuffer2 *exec,
+                       struct drm_clip_rect *cliprects,
+                       uint64_t exec_offset);
+
+       /**
+        * List of objects currently involved in rendering from the
+        * ringbuffer.
+        *
+        * Includes buffers having the contents of their GPU caches
+        * flushed, not necessarily primitives.  last_rendering_seqno
+        * represents when the rendering involved will be completed.
+        *
+        * A reference is held on the buffer while on this list.
+        */
+       struct list_head active_list;
+
+       /**
+        * List of breadcrumbs associated with GPU requests currently
+        * outstanding.
+        */
+       struct list_head request_list;
+
+       wait_queue_head_t irq_queue;
+       drm_local_map_t map;
+};
+
+static inline u32
+intel_read_status_page(struct intel_ring_buffer *ring,
+               int reg)
+{
+       u32 *regs = ring->status_page.page_addr;
+       return regs[reg];
+}
+
+int intel_init_ring_buffer(struct drm_device *dev,
+               struct intel_ring_buffer *ring);
+void intel_cleanup_ring_buffer(struct drm_device *dev,
+               struct intel_ring_buffer *ring);
+int intel_wait_ring_buffer(struct drm_device *dev,
+               struct intel_ring_buffer *ring, int n);
+int intel_wrap_ring_buffer(struct drm_device *dev,
+               struct intel_ring_buffer *ring);
+void intel_ring_begin(struct drm_device *dev,
+               struct intel_ring_buffer *ring, int n);
+void intel_ring_emit(struct drm_device *dev,
+               struct intel_ring_buffer *ring, u32 data);
+void intel_fill_struct(struct drm_device *dev,
+               struct intel_ring_buffer *ring,
+               void *data,
+               unsigned int len);
+void intel_ring_advance(struct drm_device *dev,
+               struct intel_ring_buffer *ring);
+
+u32 intel_ring_get_seqno(struct drm_device *dev,
+               struct intel_ring_buffer *ring);
+
+extern struct intel_ring_buffer render_ring;
+extern struct intel_ring_buffer bsd_ring;
+
+#endif /* _INTEL_RINGBUFFER_H_ */
index aba72c489a2f07941fc69d88516fb2a52f086363..76993ac16cc1b1b84ca4c4ff102458ae47f76c80 100644 (file)
@@ -1479,7 +1479,7 @@ intel_find_analog_connector(struct drm_device *dev)
                intel_encoder = enc_to_intel_encoder(encoder);
                if (intel_encoder->type == INTEL_OUTPUT_ANALOG) {
                        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-                               if (connector && encoder == intel_attached_encoder(connector))
+                               if (encoder == intel_attached_encoder(connector))
                                        return connector;
                        }
                }
index e13f6af0037ac4dc805a821d785bf5ef541d9c07..d4bcca8a5133b2a4565b8f7d794b4d558da5557e 100644 (file)
@@ -34,7 +34,7 @@
 static struct nouveau_dsm_priv {
        bool dsm_detected;
        acpi_handle dhandle;
-       acpi_handle dsm_handle;
+       acpi_handle rom_handle;
 } nouveau_dsm_priv;
 
 static const char nouveau_dsm_muid[] = {
@@ -107,9 +107,9 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero
 static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id)
 {
        if (id == VGA_SWITCHEROO_IGD)
-               return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_STAMINA);
+               return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA);
        else
-               return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_SPEED);
+               return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED);
 }
 
 static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,
@@ -118,7 +118,7 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,
        if (id == VGA_SWITCHEROO_IGD)
                return 0;
 
-       return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dsm_handle, state);
+       return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state);
 }
 
 static int nouveau_dsm_init(void)
@@ -151,18 +151,18 @@ static bool nouveau_dsm_pci_probe(struct pci_dev *pdev)
        dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
        if (!dhandle)
                return false;
+
        status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
        if (ACPI_FAILURE(status)) {
                return false;
        }
 
-       ret= nouveau_dsm(nvidia_handle, NOUVEAU_DSM_SUPPORTED,
-                        NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
+       ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED,
+                         NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
        if (ret < 0)
                return false;
 
        nouveau_dsm_priv.dhandle = dhandle;
-       nouveau_dsm_priv.dsm_handle = nvidia_handle;
        return true;
 }
 
@@ -173,6 +173,7 @@ static bool nouveau_dsm_detect(void)
        struct pci_dev *pdev = NULL;
        int has_dsm = 0;
        int vga_count = 0;
+
        while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
                vga_count++;
 
@@ -180,7 +181,7 @@ static bool nouveau_dsm_detect(void)
        }
 
        if (vga_count == 2 && has_dsm) {
-               acpi_get_name(nouveau_dsm_priv.dsm_handle, ACPI_FULL_PATHNAME, &buffer);
+               acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer);
                printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
                       acpi_method_name);
                nouveau_dsm_priv.dsm_detected = true;
@@ -204,3 +205,57 @@ void nouveau_unregister_dsm_handler(void)
 {
        vga_switcheroo_unregister_handler();
 }
+
+/* retrieve the ROM in 4k blocks */
+static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
+                           int offset, int len)
+{
+       acpi_status status;
+       union acpi_object rom_arg_elements[2], *obj;
+       struct acpi_object_list rom_arg;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
+
+       rom_arg.count = 2;
+       rom_arg.pointer = &rom_arg_elements[0];
+
+       rom_arg_elements[0].type = ACPI_TYPE_INTEGER;
+       rom_arg_elements[0].integer.value = offset;
+
+       rom_arg_elements[1].type = ACPI_TYPE_INTEGER;
+       rom_arg_elements[1].integer.value = len;
+
+       status = acpi_evaluate_object(rom_handle, NULL, &rom_arg, &buffer);
+       if (ACPI_FAILURE(status)) {
+               printk(KERN_INFO "failed to evaluate ROM got %s\n", acpi_format_exception(status));
+               return -ENODEV;
+       }
+       obj = (union acpi_object *)buffer.pointer;
+       memcpy(bios+offset, obj->buffer.pointer, len);
+       kfree(buffer.pointer);
+       return len;
+}
+
+bool nouveau_acpi_rom_supported(struct pci_dev *pdev)
+{
+       acpi_status status;
+       acpi_handle dhandle, rom_handle;
+
+       if (!nouveau_dsm_priv.dsm_detected)
+               return false;
+
+       dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
+       if (!dhandle)
+               return false;
+
+       status = acpi_get_handle(dhandle, "_ROM", &rom_handle);
+       if (ACPI_FAILURE(status))
+               return false;
+
+       nouveau_dsm_priv.rom_handle = rom_handle;
+       return true;
+}
+
+int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
+{
+       return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
+}
index e7e69ccce5c9985ba77b7e7790582f984c8efdb9..fc924b64919529cfccc14a85c3eb28ae0ab8f50d 100644 (file)
@@ -178,6 +178,25 @@ out:
        pci_disable_rom(dev->pdev);
 }
 
+static void load_vbios_acpi(struct drm_device *dev, uint8_t *data)
+{
+       int i;
+       int ret;
+       int size = 64 * 1024;
+
+       if (!nouveau_acpi_rom_supported(dev->pdev))
+               return;
+
+       for (i = 0; i < (size / ROM_BIOS_PAGE); i++) {
+               ret = nouveau_acpi_get_bios_chunk(data,
+                                                 (i * ROM_BIOS_PAGE),
+                                                 ROM_BIOS_PAGE);
+               if (ret <= 0)
+                       break;
+       }
+       return;
+}
+
 struct methods {
        const char desc[8];
        void (*loadbios)(struct drm_device *, uint8_t *);
@@ -191,6 +210,7 @@ static struct methods nv04_methods[] = {
 };
 
 static struct methods nv50_methods[] = {
+       { "ACPI", load_vbios_acpi, true },
        { "PRAMIN", load_vbios_pramin, true },
        { "PROM", load_vbios_prom, false },
        { "PCIROM", load_vbios_pci, true },
@@ -814,7 +834,7 @@ init_i2c_device_find(struct drm_device *dev, int i2c_index)
        if (i2c_index == 0x81)
                i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4;
 
-       if (i2c_index > DCB_MAX_NUM_I2C_ENTRIES) {
+       if (i2c_index >= DCB_MAX_NUM_I2C_ENTRIES) {
                NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index);
                return NULL;
        }
@@ -2807,7 +2827,10 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 
                BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
 
-               nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
+               BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n",
+                       offset, gpio->tag, gpio->state_default);
+               if (bios->execute)
+                       nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
 
                /* The NVIDIA binary driver doesn't appear to actually do
                 * any of this, my VBIOS does however.
@@ -3897,7 +3920,8 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
 
 static uint8_t *
 bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
-                        uint16_t record, int record_len, int record_nr)
+                        uint16_t record, int record_len, int record_nr,
+                        bool match_link)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nvbios *bios = &dev_priv->vbios;
@@ -3905,12 +3929,28 @@ bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
        uint16_t table;
        int i, v;
 
+       switch (dcbent->type) {
+       case OUTPUT_TMDS:
+       case OUTPUT_LVDS:
+       case OUTPUT_DP:
+               break;
+       default:
+               match_link = false;
+               break;
+       }
+
        for (i = 0; i < record_nr; i++, record += record_len) {
                table = ROM16(bios->data[record]);
                if (!table)
                        continue;
                entry = ROM32(bios->data[table]);
 
+               if (match_link) {
+                       v = (entry & 0x00c00000) >> 22;
+                       if (!(v & dcbent->sorconf.link))
+                               continue;
+               }
+
                v = (entry & 0x000f0000) >> 16;
                if (!(v & dcbent->or))
                        continue;
@@ -3952,7 +3992,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
        *length = table[4];
        return bios_output_config_match(dev, dcbent,
                                        bios->display.dp_table_ptr + table[1],
-                                       table[2], table[3]);
+                                       table[2], table[3], table[0] >= 0x21);
 }
 
 int
@@ -4041,7 +4081,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
                        dcbent->type, dcbent->location, dcbent->or);
        otable = bios_output_config_match(dev, dcbent, table[1] +
                                          bios->display.script_table_ptr,
-                                         table[2], table[3]);
+                                         table[2], table[3], table[0] >= 0x21);
        if (!otable) {
                NV_ERROR(dev, "Couldn't find matching output script table\n");
                return 1;
@@ -5533,12 +5573,6 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
        entry->bus = (conn >> 16) & 0xf;
        entry->location = (conn >> 20) & 0x3;
        entry->or = (conn >> 24) & 0xf;
-       /*
-        * Normal entries consist of a single bit, but dual link has the
-        * next most significant bit set too
-        */
-       entry->duallink_possible =
-                       ((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
 
        switch (entry->type) {
        case OUTPUT_ANALOG:
@@ -5622,6 +5656,16 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
                break;
        }
 
+       if (dcb->version < 0x40) {
+               /* Normal entries consist of a single bit, but dual link has
+                * the next most significant bit set too
+                */
+               entry->duallink_possible =
+                       ((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
+       } else {
+               entry->duallink_possible = (entry->sorconf.link == 3);
+       }
+
        /* unsure what DCB version introduces this, 3.0? */
        if (conf & 0x100000)
                entry->i2c_upper_default = true;
@@ -6205,6 +6249,30 @@ nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
                nouveau_i2c_fini(dev, entry);
 }
 
+static bool
+nouveau_bios_posted(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       bool was_locked;
+       unsigned htotal;
+
+       if (dev_priv->chipset >= NV_50) {
+               if (NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
+                   NVReadVgaCrtc(dev, 0, 0x1a) == 0)
+                       return false;
+               return true;
+       }
+
+       was_locked = NVLockVgaCrtcs(dev, false);
+       htotal  = NVReadVgaCrtc(dev, 0, 0x06);
+       htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x01) << 8;
+       htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x20) << 4;
+       htotal |= (NVReadVgaCrtc(dev, 0, 0x25) & 0x01) << 10;
+       htotal |= (NVReadVgaCrtc(dev, 0, 0x41) & 0x01) << 11;
+       NVLockVgaCrtcs(dev, was_locked);
+       return (htotal != 0);
+}
+
 int
 nouveau_bios_init(struct drm_device *dev)
 {
@@ -6239,11 +6307,9 @@ nouveau_bios_init(struct drm_device *dev)
        bios->execute = false;
 
        /* ... unless card isn't POSTed already */
-       if (dev_priv->card_type >= NV_10 &&
-           NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
-           NVReadVgaCrtc(dev, 0, 0x1a) == 0) {
+       if (!nouveau_bios_posted(dev)) {
                NV_INFO(dev, "Adaptor not initialised\n");
-               if (dev_priv->card_type < NV_50) {
+               if (dev_priv->card_type < NV_40) {
                        NV_ERROR(dev, "Unable to POST this chipset\n");
                        return -ENODEV;
                }
index 266b0ff441af37b75ee555360bdcd68ce1cd881f..149ed224c3cb48c86c56e2f4b9bb18a599190d10 100644 (file)
@@ -432,24 +432,27 @@ nouveau_connector_set_property(struct drm_connector *connector,
 }
 
 static struct drm_display_mode *
-nouveau_connector_native_mode(struct nouveau_connector *connector)
+nouveau_connector_native_mode(struct drm_connector *connector)
 {
-       struct drm_device *dev = connector->base.dev;
+       struct drm_connector_helper_funcs *helper = connector->helper_private;
+       struct nouveau_connector *nv_connector = nouveau_connector(connector);
+       struct drm_device *dev = connector->dev;
        struct drm_display_mode *mode, *largest = NULL;
        int high_w = 0, high_h = 0, high_v = 0;
 
-       /* Use preferred mode if there is one.. */
-       list_for_each_entry(mode, &connector->base.probed_modes, head) {
+       list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
+               if (helper->mode_valid(connector, mode) != MODE_OK)
+                       continue;
+
+               /* Use preferred mode if there is one.. */
                if (mode->type & DRM_MODE_TYPE_PREFERRED) {
                        NV_DEBUG_KMS(dev, "native mode from preferred\n");
                        return drm_mode_duplicate(dev, mode);
                }
-       }
 
-       /* Otherwise, take the resolution with the largest width, then height,
-        * then vertical refresh
-        */
-       list_for_each_entry(mode, &connector->base.probed_modes, head) {
+               /* Otherwise, take the resolution with the largest width, then
+                * height, then vertical refresh
+                */
                if (mode->hdisplay < high_w)
                        continue;
 
@@ -553,7 +556,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
         */
        if (!nv_connector->native_mode)
                nv_connector->native_mode =
-                       nouveau_connector_native_mode(nv_connector);
+                       nouveau_connector_native_mode(connector);
        if (ret == 0 && nv_connector->native_mode) {
                struct drm_display_mode *mode;
 
@@ -584,9 +587,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
 
        switch (nv_encoder->dcb->type) {
        case OUTPUT_LVDS:
-               BUG_ON(!nv_connector->native_mode);
-               if (mode->hdisplay > nv_connector->native_mode->hdisplay ||
-                   mode->vdisplay > nv_connector->native_mode->vdisplay)
+               if (nv_connector->native_mode &&
+                   (mode->hdisplay > nv_connector->native_mode->hdisplay ||
+                    mode->vdisplay > nv_connector->native_mode->vdisplay))
                        return MODE_PANEL;
 
                min_clock = 0;
@@ -594,8 +597,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
                break;
        case OUTPUT_TMDS:
                if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) ||
-                   (dev_priv->card_type < NV_50 &&
-                    !nv_encoder->dcb->duallink_possible))
+                   !nv_encoder->dcb->duallink_possible)
                        max_clock = 165000;
                else
                        max_clock = 330000;
@@ -729,7 +731,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
        if (ret == 0)
                goto out;
        nv_connector->detected_encoder = nv_encoder;
-       nv_connector->native_mode = nouveau_connector_native_mode(nv_connector);
+       nv_connector->native_mode = nouveau_connector_native_mode(connector);
        list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
                drm_mode_remove(connector, mode);
 
index 49fa7b2d257e8e739391720ffaf66e8eea86ee45..cb1ce2a0916257ecbbe8ea72949baa8a80b32c56 100644 (file)
@@ -40,6 +40,8 @@ struct nouveau_crtc {
        int sharpness;
        int last_dpms;
 
+       int cursor_saved_x, cursor_saved_y;
+
        struct {
                int cpp;
                bool blanked;
index c6079e36669d9f43893db8ad88623dbb70b6147c..273770432298b72ae5687505e156fe5b03e0e4e4 100644 (file)
@@ -175,6 +175,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
                nouveau_bo_unpin(nouveau_fb->nvbo);
        }
 
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+               nouveau_bo_unmap(nv_crtc->cursor.nvbo);
+               nouveau_bo_unpin(nv_crtc->cursor.nvbo);
+       }
+
        NV_INFO(dev, "Evicting buffers...\n");
        ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
 
@@ -314,12 +321,34 @@ nouveau_pci_resume(struct pci_dev *pdev)
                nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
        }
 
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+               int ret;
+
+               ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
+               if (!ret)
+                       ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
+               if (ret)
+                       NV_ERROR(dev, "Could not pin/map cursor.\n");
+       }
+
        if (dev_priv->card_type < NV_50) {
                nv04_display_restore(dev);
                NVLockVgaCrtcs(dev, false);
        } else
                nv50_display_init(dev);
 
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+               nv_crtc->cursor.set_offset(nv_crtc,
+                                       nv_crtc->cursor.nvbo->bo.offset -
+                                       dev_priv->vm_vram_base);
+
+               nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
+                       nv_crtc->cursor_saved_y);
+       }
+
        /* Force CLUT to get re-loaded during modeset */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
index 5b134438effebcda05e2fbb8c4a74581f6148bcc..c697191064894345efbbf76bf3bfd1fc83188270 100644 (file)
@@ -851,12 +851,17 @@ extern int  nouveau_dma_init(struct nouveau_channel *);
 extern int  nouveau_dma_wait(struct nouveau_channel *, int slots, int size);
 
 /* nouveau_acpi.c */
+#define ROM_BIOS_PAGE 4096
 #if defined(CONFIG_ACPI)
 void nouveau_register_dsm_handler(void);
 void nouveau_unregister_dsm_handler(void);
+int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
+bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
 #else
 static inline void nouveau_register_dsm_handler(void) {}
 static inline void nouveau_unregister_dsm_handler(void) {}
+static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; }
+static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
 #endif
 
 /* nouveau_backlight.c */
index fd4a2df715e96d40bd28c2cfea428ad6fae03cd2..c9a4a0d2a11593a0d2010bdd979352c4d5cd6003 100644 (file)
@@ -377,6 +377,7 @@ int nouveau_fbcon_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_fbdev *nfbdev;
+       int ret;
 
        nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
        if (!nfbdev)
@@ -386,7 +387,12 @@ int nouveau_fbcon_init(struct drm_device *dev)
        dev_priv->nfbdev = nfbdev;
        nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs;
 
-       drm_fb_helper_init(dev, &nfbdev->helper, 2, 4);
+       ret = drm_fb_helper_init(dev, &nfbdev->helper, 2, 4);
+       if (ret) {
+               kfree(nfbdev);
+               return ret;
+       }
+
        drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
        drm_fb_helper_initial_config(&nfbdev->helper, 32);
        return 0;
index 775a7017af6437da7c149dfda2a04d172704fdb2..c1fd42b0dad19cb18e34463548c8ff4b60093747 100644 (file)
@@ -540,7 +540,8 @@ nouveau_mem_detect(struct drm_device *dev)
                dev_priv->vram_size  = nv_rd32(dev, NV04_FIFO_DATA);
                dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK;
                if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
-                       dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12;
+                       dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
+                       dev_priv->vram_sys_base <<= 12;
        }
 
        NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
index e632339c323e5bd03efe592f554875117322b7b1..b02a231d6937489fe972bfc813dc72d5d421aa70 100644 (file)
@@ -376,12 +376,15 @@ out_err:
 static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
                                         enum vga_switcheroo_state state)
 {
+       struct drm_device *dev = pci_get_drvdata(pdev);
        pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
        if (state == VGA_SWITCHEROO_ON) {
                printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
                nouveau_pci_resume(pdev);
+               drm_kms_helper_poll_enable(dev);
        } else {
                printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
+               drm_kms_helper_poll_disable(dev);
                nouveau_pci_suspend(pdev, pmm);
        }
 }
@@ -776,29 +779,24 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
                        return ret;
        }
 
-       /* map larger RAMIN aperture on NV40 cards */
-       dev_priv->ramin  = NULL;
+       /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */
        if (dev_priv->card_type >= NV_40) {
                int ramin_bar = 2;
                if (pci_resource_len(dev->pdev, ramin_bar) == 0)
                        ramin_bar = 3;
 
                dev_priv->ramin_size = pci_resource_len(dev->pdev, ramin_bar);
-               dev_priv->ramin = ioremap(
-                               pci_resource_start(dev->pdev, ramin_bar),
+               dev_priv->ramin =
+                       ioremap(pci_resource_start(dev->pdev, ramin_bar),
                                dev_priv->ramin_size);
                if (!dev_priv->ramin) {
-                       NV_ERROR(dev, "Failed to init RAMIN mapping, "
-                                     "limited instance memory available\n");
+                       NV_ERROR(dev, "Failed to PRAMIN BAR");
+                       return -ENOMEM;
                }
-       }
-
-       /* On older cards (or if the above failed), create a map covering
-        * the BAR0 PRAMIN aperture */
-       if (!dev_priv->ramin) {
+       } else {
                dev_priv->ramin_size = 1 * 1024 * 1024;
                dev_priv->ramin = ioremap(mmio_start_offs + NV_RAMIN,
-                                                       dev_priv->ramin_size);
+                                         dev_priv->ramin_size);
                if (!dev_priv->ramin) {
                        NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n");
                        return -ENOMEM;
@@ -913,6 +911,9 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
        case NOUVEAU_GETPARAM_VM_VRAM_BASE:
                getparam->value = dev_priv->vm_vram_base;
                break;
+       case NOUVEAU_GETPARAM_PTIMER_TIME:
+               getparam->value = dev_priv->engine.timer.read(dev);
+               break;
        case NOUVEAU_GETPARAM_GRAPH_UNITS:
                /* NV40 and NV50 versions are quite different, but register
                 * address is the same. User is supposed to know the card
index 89a91b9d8b258d54e24c2b3725727824c7a18df0..aaf3de3bc816c5e0d9e1d34fcd4847fa2fa3e5db 100644 (file)
@@ -20,6 +20,7 @@ nv04_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
 static void
 nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
 {
+       nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
        NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index,
                      NV_PRAMDAC_CU_START_POS,
                      XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |
index 753e723adb3afb9e0dc733d4ef416a4468b3aacc..03ad7ab14f0960e1729674cd637a15ff325ae169 100644 (file)
@@ -107,6 +107,7 @@ nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
 {
        struct drm_device *dev = nv_crtc->base.dev;
 
+       nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
        nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index),
                ((y & 0xFFFF) << 16) | (x & 0xFFFF));
        /* Needed to make the cursor move. */
index a95e6941ba884b37f041667a4644fea56c5b57b8..32611bd30e6db6524a44588f06602c33266fb4bc 100644 (file)
@@ -6,10 +6,16 @@
 int
 nv50_fb_init(struct drm_device *dev)
 {
-       /* This is needed to get meaningful information from 100c90
-        * on traps. No idea what these values mean exactly. */
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 
+       /* Not a clue what this is exactly.  Without pointing it at a
+        * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
+        * cause IOMMU "read from address 0" errors (rh#561267)
+        */
+       nv_wr32(dev, 0x100c08, dev_priv->gart_info.sg_dummy_bus >> 8);
+
+       /* This is needed to get meaningful information from 100c90
+        * on traps. No idea what these values mean exactly. */
        switch (dev_priv->chipset) {
        case 0x50:
                nv_wr32(dev, 0x100c90, 0x0707ff);
index c61782b314e799c59c2fc25972eaf8965169cbae..bb47ad737267a07ecfdc1071a6ebf7f2fdb6f9ec 100644 (file)
@@ -31,7 +31,7 @@ nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift)
 {
        const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
 
-       if (gpio->line > 32)
+       if (gpio->line >= 32)
                return -EINVAL;
 
        *reg = nv50_gpio_reg[gpio->line >> 3];
index b11eaf9c5c7cd0575eec63e20d7217b7c8fd49c1..812778db76ac185b5943a8257ae401ff82f27202 100644 (file)
@@ -274,7 +274,6 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
 int
 nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
 {
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_encoder *nv_encoder = NULL;
        struct drm_encoder *encoder;
        bool dum;
@@ -324,11 +323,7 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
                int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
                uint32_t tmp;
 
-               if (dev_priv->chipset < 0x90 ||
-                   dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0)
-                       tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or));
-               else
-                       tmp = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or));
+               tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
 
                switch ((tmp & 0x00000f00) >> 8) {
                case 8:
index 3c91312dea9a00d8aa93b097d2d5d476487fb2d8..84b1f2729d430deaddcf6e4241a1886339c0123b 100644 (file)
@@ -33,6 +33,9 @@ $(obj)/rs600_reg_safe.h: $(src)/reg_srcs/rs600 $(obj)/mkregtable
 $(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable
        $(call if_changed,mkregtable)
 
+$(obj)/evergreen_reg_safe.h: $(src)/reg_srcs/evergreen $(obj)/mkregtable
+       $(call if_changed,mkregtable)
+
 $(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h
 
 $(obj)/r200.o: $(obj)/r200_reg_safe.h
@@ -47,6 +50,8 @@ $(obj)/rs600.o: $(obj)/rs600_reg_safe.h
 
 $(obj)/r600_cs.o: $(obj)/r600_reg_safe.h
 
+$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h
+
 radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
        radeon_irq.o r300_cmdbuf.o r600_cp.o
 # add KMS driver
@@ -60,7 +65,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
        rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
        r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
        r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
-       evergreen.o
+       evergreen.o evergreen_cs.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
index f3f2827017ef39603bae514432f875a51472eec1..8c2d6478a2213d82637a4270b4215a676481896b 100644 (file)
@@ -498,7 +498,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                if ((rdev->family == CHIP_RS600) ||
                    (rdev->family == CHIP_RS690) ||
                    (rdev->family == CHIP_RS740))
-                       pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
+                       pll->flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/
                                       RADEON_PLL_PREFER_CLOSEST_LOWER);
 
                if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)        /* range limits??? */
index 8c8e4d3cbaa377773d9fc39b5035a928f93ddf55..1caf625e472b607b92b2841f0dcf7fae44785cde 100644 (file)
@@ -41,7 +41,18 @@ void evergreen_fini(struct radeon_device *rdev);
 
 void evergreen_pm_misc(struct radeon_device *rdev)
 {
-
+       int req_ps_idx = rdev->pm.requested_power_state_index;
+       int req_cm_idx = rdev->pm.requested_clock_mode_index;
+       struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
+       struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
+
+       if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
+               if (voltage->voltage != rdev->pm.current_vddc) {
+                       radeon_atom_set_voltage(rdev, voltage->voltage);
+                       rdev->pm.current_vddc = voltage->voltage;
+                       DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
+               }
+       }
 }
 
 void evergreen_pm_prepare(struct radeon_device *rdev)
@@ -596,7 +607,7 @@ static void evergreen_mc_program(struct radeon_device *rdev)
        WREG32(MC_VM_FB_LOCATION, tmp);
        WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
        WREG32(HDP_NONSURFACE_INFO, (2 << 7));
-       WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
+       WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
        if (rdev->flags & RADEON_IS_AGP) {
                WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
                WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
@@ -1211,11 +1222,11 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
                ps_thread_count = 128;
 
        sq_thread_resource_mgmt = NUM_PS_THREADS(ps_thread_count);
-       sq_thread_resource_mgmt |= NUM_VS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
-       sq_thread_resource_mgmt |= NUM_GS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
-       sq_thread_resource_mgmt |= NUM_ES_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
-       sq_thread_resource_mgmt_2 = NUM_HS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
-       sq_thread_resource_mgmt_2 |= NUM_LS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
+       sq_thread_resource_mgmt |= NUM_VS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+       sq_thread_resource_mgmt |= NUM_GS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+       sq_thread_resource_mgmt |= NUM_ES_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+       sq_thread_resource_mgmt_2 = NUM_HS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+       sq_thread_resource_mgmt_2 |= NUM_LS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
 
        sq_stack_resource_mgmt_1 = NUM_PS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6);
        sq_stack_resource_mgmt_1 |= NUM_VS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6);
@@ -1249,6 +1260,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        WREG32(VGT_GS_VERTEX_REUSE, 16);
        WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
 
+       WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, 14);
+       WREG32(VGT_OUT_DEALLOC_CNTL, 16);
+
        WREG32(CB_PERF_CTR0_SEL_0, 0);
        WREG32(CB_PERF_CTR0_SEL_1, 0);
        WREG32(CB_PERF_CTR1_SEL_0, 0);
@@ -1258,6 +1272,26 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        WREG32(CB_PERF_CTR3_SEL_0, 0);
        WREG32(CB_PERF_CTR3_SEL_1, 0);
 
+       /* clear render buffer base addresses */
+       WREG32(CB_COLOR0_BASE, 0);
+       WREG32(CB_COLOR1_BASE, 0);
+       WREG32(CB_COLOR2_BASE, 0);
+       WREG32(CB_COLOR3_BASE, 0);
+       WREG32(CB_COLOR4_BASE, 0);
+       WREG32(CB_COLOR5_BASE, 0);
+       WREG32(CB_COLOR6_BASE, 0);
+       WREG32(CB_COLOR7_BASE, 0);
+       WREG32(CB_COLOR8_BASE, 0);
+       WREG32(CB_COLOR9_BASE, 0);
+       WREG32(CB_COLOR10_BASE, 0);
+       WREG32(CB_COLOR11_BASE, 0);
+
+       /* set the shader const cache sizes to 0 */
+       for (i = SQ_ALU_CONST_BUFFER_SIZE_PS_0; i < 0x28200; i += 4)
+               WREG32(i, 0);
+       for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4)
+               WREG32(i, 0);
+
        hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
        WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
 
@@ -2148,7 +2182,7 @@ int evergreen_init(struct radeon_device *rdev)
        if (r)
                return r;
 
-       rdev->accel_working = false;
+       rdev->accel_working = true;
        r = evergreen_startup(rdev);
        if (r) {
                dev_err(rdev->dev, "disabling GPU acceleration\n");
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
new file mode 100644 (file)
index 0000000..010963d
--- /dev/null
@@ -0,0 +1,1356 @@
+/*
+ * Copyright 2010 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon.h"
+#include "evergreend.h"
+#include "evergreen_reg_safe.h"
+
+static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
+                                         struct radeon_cs_reloc **cs_reloc);
+
+struct evergreen_cs_track {
+       u32                     group_size;
+       u32                     nbanks;
+       u32                     npipes;
+       /* value we track */
+       u32                     nsamples;
+       u32                     cb_color_base_last[12];
+       struct radeon_bo        *cb_color_bo[12];
+       u32                     cb_color_bo_offset[12];
+       struct radeon_bo        *cb_color_fmask_bo[8];
+       struct radeon_bo        *cb_color_cmask_bo[8];
+       u32                     cb_color_info[12];
+       u32                     cb_color_view[12];
+       u32                     cb_color_pitch_idx[12];
+       u32                     cb_color_slice_idx[12];
+       u32                     cb_color_dim_idx[12];
+       u32                     cb_color_dim[12];
+       u32                     cb_color_pitch[12];
+       u32                     cb_color_slice[12];
+       u32                     cb_color_cmask_slice[8];
+       u32                     cb_color_fmask_slice[8];
+       u32                     cb_target_mask;
+       u32                     cb_shader_mask;
+       u32                     vgt_strmout_config;
+       u32                     vgt_strmout_buffer_config;
+       u32                     db_depth_control;
+       u32                     db_depth_view;
+       u32                     db_depth_size;
+       u32                     db_depth_size_idx;
+       u32                     db_z_info;
+       u32                     db_z_idx;
+       u32                     db_z_read_offset;
+       u32                     db_z_write_offset;
+       struct radeon_bo        *db_z_read_bo;
+       struct radeon_bo        *db_z_write_bo;
+       u32                     db_s_info;
+       u32                     db_s_idx;
+       u32                     db_s_read_offset;
+       u32                     db_s_write_offset;
+       struct radeon_bo        *db_s_read_bo;
+       struct radeon_bo        *db_s_write_bo;
+};
+
+static void evergreen_cs_track_init(struct evergreen_cs_track *track)
+{
+       int i;
+
+       for (i = 0; i < 8; i++) {
+               track->cb_color_fmask_bo[i] = NULL;
+               track->cb_color_cmask_bo[i] = NULL;
+               track->cb_color_cmask_slice[i] = 0;
+               track->cb_color_fmask_slice[i] = 0;
+       }
+
+       for (i = 0; i < 12; i++) {
+               track->cb_color_base_last[i] = 0;
+               track->cb_color_bo[i] = NULL;
+               track->cb_color_bo_offset[i] = 0xFFFFFFFF;
+               track->cb_color_info[i] = 0;
+               track->cb_color_view[i] = 0;
+               track->cb_color_pitch_idx[i] = 0;
+               track->cb_color_slice_idx[i] = 0;
+               track->cb_color_dim[i] = 0;
+               track->cb_color_pitch[i] = 0;
+               track->cb_color_slice[i] = 0;
+               track->cb_color_dim[i] = 0;
+       }
+       track->cb_target_mask = 0xFFFFFFFF;
+       track->cb_shader_mask = 0xFFFFFFFF;
+
+       track->db_depth_view = 0xFFFFC000;
+       track->db_depth_size = 0xFFFFFFFF;
+       track->db_depth_size_idx = 0;
+       track->db_depth_control = 0xFFFFFFFF;
+       track->db_z_info = 0xFFFFFFFF;
+       track->db_z_idx = 0xFFFFFFFF;
+       track->db_z_read_offset = 0xFFFFFFFF;
+       track->db_z_write_offset = 0xFFFFFFFF;
+       track->db_z_read_bo = NULL;
+       track->db_z_write_bo = NULL;
+       track->db_s_info = 0xFFFFFFFF;
+       track->db_s_idx = 0xFFFFFFFF;
+       track->db_s_read_offset = 0xFFFFFFFF;
+       track->db_s_write_offset = 0xFFFFFFFF;
+       track->db_s_read_bo = NULL;
+       track->db_s_write_bo = NULL;
+}
+
+static inline int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
+{
+       /* XXX fill in */
+       return 0;
+}
+
+static int evergreen_cs_track_check(struct radeon_cs_parser *p)
+{
+       struct evergreen_cs_track *track = p->track;
+
+       /* we don't support stream out buffer yet */
+       if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {
+               dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
+               return -EINVAL;
+       }
+
+       /* XXX fill in */
+       return 0;
+}
+
+/**
+ * evergreen_cs_packet_parse() - parse cp packet and point ib index to next packet
+ * @parser:    parser structure holding parsing context.
+ * @pkt:       where to store packet informations
+ *
+ * Assume that chunk_ib_index is properly set. Will return -EINVAL
+ * if packet is bigger than remaining ib size. or if packets is unknown.
+ **/
+int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
+                             struct radeon_cs_packet *pkt,
+                             unsigned idx)
+{
+       struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
+       uint32_t header;
+
+       if (idx >= ib_chunk->length_dw) {
+               DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
+                         idx, ib_chunk->length_dw);
+               return -EINVAL;
+       }
+       header = radeon_get_ib_value(p, idx);
+       pkt->idx = idx;
+       pkt->type = CP_PACKET_GET_TYPE(header);
+       pkt->count = CP_PACKET_GET_COUNT(header);
+       pkt->one_reg_wr = 0;
+       switch (pkt->type) {
+       case PACKET_TYPE0:
+               pkt->reg = CP_PACKET0_GET_REG(header);
+               break;
+       case PACKET_TYPE3:
+               pkt->opcode = CP_PACKET3_GET_OPCODE(header);
+               break;
+       case PACKET_TYPE2:
+               pkt->count = -1;
+               break;
+       default:
+               DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
+               return -EINVAL;
+       }
+       if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
+               DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
+                         pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3
+ * @parser:            parser structure holding parsing context.
+ * @data:              pointer to relocation data
+ * @offset_start:      starting offset
+ * @offset_mask:       offset mask (to align start offset on)
+ * @reloc:             reloc informations
+ *
+ * Check next packet is relocation packet3, do bo validation and compute
+ * GPU offset using the provided start.
+ **/
+static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
+                                         struct radeon_cs_reloc **cs_reloc)
+{
+       struct radeon_cs_chunk *relocs_chunk;
+       struct radeon_cs_packet p3reloc;
+       unsigned idx;
+       int r;
+
+       if (p->chunk_relocs_idx == -1) {
+               DRM_ERROR("No relocation chunk !\n");
+               return -EINVAL;
+       }
+       *cs_reloc = NULL;
+       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
+       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
+       if (r) {
+               return r;
+       }
+       p->idx += p3reloc.count + 2;
+       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+               DRM_ERROR("No packet3 for relocation for packet at %d.\n",
+                         p3reloc.idx);
+               return -EINVAL;
+       }
+       idx = radeon_get_ib_value(p, p3reloc.idx + 1);
+       if (idx >= relocs_chunk->length_dw) {
+               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
+                         idx, relocs_chunk->length_dw);
+               return -EINVAL;
+       }
+       /* FIXME: we assume reloc size is 4 dwords */
+       *cs_reloc = p->relocs_ptr[(idx / 4)];
+       return 0;
+}
+
+/**
+ * evergreen_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
+ * @parser:            parser structure holding parsing context.
+ *
+ * Check next packet is relocation packet3, do bo validation and compute
+ * GPU offset using the provided start.
+ **/
+static inline int evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+{
+       struct radeon_cs_packet p3reloc;
+       int r;
+
+       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
+       if (r) {
+               return 0;
+       }
+       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+               return 0;
+       }
+       return 1;
+}
+
+/**
+ * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
+ * @parser:            parser structure holding parsing context.
+ *
+ * Userspace sends a special sequence for VLINE waits.
+ * PACKET0 - VLINE_START_END + value
+ * PACKET3 - WAIT_REG_MEM poll vline status reg
+ * RELOC (P3) - crtc_id in reloc.
+ *
+ * This function parses this and relocates the VLINE START END
+ * and WAIT_REG_MEM packets to the correct crtc.
+ * It also detects a switched off crtc and nulls out the
+ * wait in that case.
+ */
+static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
+{
+       struct drm_mode_object *obj;
+       struct drm_crtc *crtc;
+       struct radeon_crtc *radeon_crtc;
+       struct radeon_cs_packet p3reloc, wait_reg_mem;
+       int crtc_id;
+       int r;
+       uint32_t header, h_idx, reg, wait_reg_mem_info;
+       volatile uint32_t *ib;
+
+       ib = p->ib->ptr;
+
+       /* parse the WAIT_REG_MEM */
+       r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx);
+       if (r)
+               return r;
+
+       /* check its a WAIT_REG_MEM */
+       if (wait_reg_mem.type != PACKET_TYPE3 ||
+           wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
+               DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
+               r = -EINVAL;
+               return r;
+       }
+
+       wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
+       /* bit 4 is reg (0) or mem (1) */
+       if (wait_reg_mem_info & 0x10) {
+               DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
+               r = -EINVAL;
+               return r;
+       }
+       /* waiting for value to be equal */
+       if ((wait_reg_mem_info & 0x7) != 0x3) {
+               DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
+               r = -EINVAL;
+               return r;
+       }
+       if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
+               DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
+               r = -EINVAL;
+               return r;
+       }
+
+       if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
+               DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
+               r = -EINVAL;
+               return r;
+       }
+
+       /* jump over the NOP */
+       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
+       if (r)
+               return r;
+
+       h_idx = p->idx - 2;
+       p->idx += wait_reg_mem.count + 2;
+       p->idx += p3reloc.count + 2;
+
+       header = radeon_get_ib_value(p, h_idx);
+       crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
+       reg = CP_PACKET0_GET_REG(header);
+       mutex_lock(&p->rdev->ddev->mode_config.mutex);
+       obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
+       if (!obj) {
+               DRM_ERROR("cannot find crtc %d\n", crtc_id);
+               r = -EINVAL;
+               goto out;
+       }
+       crtc = obj_to_crtc(obj);
+       radeon_crtc = to_radeon_crtc(crtc);
+       crtc_id = radeon_crtc->crtc_id;
+
+       if (!crtc->enabled) {
+               /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
+               ib[h_idx + 2] = PACKET2(0);
+               ib[h_idx + 3] = PACKET2(0);
+               ib[h_idx + 4] = PACKET2(0);
+               ib[h_idx + 5] = PACKET2(0);
+               ib[h_idx + 6] = PACKET2(0);
+               ib[h_idx + 7] = PACKET2(0);
+               ib[h_idx + 8] = PACKET2(0);
+       } else {
+               switch (reg) {
+               case EVERGREEN_VLINE_START_END:
+                       header &= ~R600_CP_PACKET0_REG_MASK;
+                       header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
+                       ib[h_idx] = header;
+                       ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
+                       break;
+               default:
+                       DRM_ERROR("unknown crtc reloc\n");
+                       r = -EINVAL;
+                       goto out;
+               }
+       }
+out:
+       mutex_unlock(&p->rdev->ddev->mode_config.mutex);
+       return r;
+}
+
+static int evergreen_packet0_check(struct radeon_cs_parser *p,
+                                  struct radeon_cs_packet *pkt,
+                                  unsigned idx, unsigned reg)
+{
+       int r;
+
+       switch (reg) {
+       case EVERGREEN_VLINE_START_END:
+               r = evergreen_cs_packet_parse_vline(p);
+               if (r) {
+                       DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                       idx, reg);
+                       return r;
+               }
+               break;
+       default:
+               printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
+                      reg, idx);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,
+                                     struct radeon_cs_packet *pkt)
+{
+       unsigned reg, i;
+       unsigned idx;
+       int r;
+
+       idx = pkt->idx + 1;
+       reg = pkt->reg;
+       for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
+               r = evergreen_packet0_check(p, pkt, idx, reg);
+               if (r) {
+                       return r;
+               }
+       }
+       return 0;
+}
+
+/**
+ * evergreen_cs_check_reg() - check if register is authorized or not
+ * @parser: parser structure holding parsing context
+ * @reg: register we are testing
+ * @idx: index into the cs buffer
+ *
+ * This function will test against evergreen_reg_safe_bm and return 0
+ * if register is safe. If register is not flag as safe this function
+ * will test it against a list of register needind special handling.
+ */
+static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+{
+       struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
+       struct radeon_cs_reloc *reloc;
+       u32 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
+       u32 m, i, tmp, *ib;
+       int r;
+
+       i = (reg >> 7);
+       if (i > last_reg) {
+               dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
+               return -EINVAL;
+       }
+       m = 1 << ((reg >> 2) & 31);
+       if (!(evergreen_reg_safe_bm[i] & m))
+               return 0;
+       ib = p->ib->ptr;
+       switch (reg) {
+       /* force following reg to 0 in an attemp to disable out buffer
+        * which will need us to better understand how it works to perform
+        * security check on it (Jerome)
+        */
+       case SQ_ESGS_RING_SIZE:
+       case SQ_GSVS_RING_SIZE:
+       case SQ_ESTMP_RING_SIZE:
+       case SQ_GSTMP_RING_SIZE:
+       case SQ_HSTMP_RING_SIZE:
+       case SQ_LSTMP_RING_SIZE:
+       case SQ_PSTMP_RING_SIZE:
+       case SQ_VSTMP_RING_SIZE:
+       case SQ_ESGS_RING_ITEMSIZE:
+       case SQ_ESTMP_RING_ITEMSIZE:
+       case SQ_GSTMP_RING_ITEMSIZE:
+       case SQ_GSVS_RING_ITEMSIZE:
+       case SQ_GS_VERT_ITEMSIZE:
+       case SQ_GS_VERT_ITEMSIZE_1:
+       case SQ_GS_VERT_ITEMSIZE_2:
+       case SQ_GS_VERT_ITEMSIZE_3:
+       case SQ_GSVS_RING_OFFSET_1:
+       case SQ_GSVS_RING_OFFSET_2:
+       case SQ_GSVS_RING_OFFSET_3:
+       case SQ_HSTMP_RING_ITEMSIZE:
+       case SQ_LSTMP_RING_ITEMSIZE:
+       case SQ_PSTMP_RING_ITEMSIZE:
+       case SQ_VSTMP_RING_ITEMSIZE:
+       case VGT_TF_RING_SIZE:
+               /* get value to populate the IB don't remove */
+               tmp =radeon_get_ib_value(p, idx);
+               ib[idx] = 0;
+               break;
+       case DB_DEPTH_CONTROL:
+               track->db_depth_control = radeon_get_ib_value(p, idx);
+               break;
+       case DB_Z_INFO:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->db_z_info = radeon_get_ib_value(p, idx);
+               ib[idx] &= ~Z_ARRAY_MODE(0xf);
+               track->db_z_info &= ~Z_ARRAY_MODE(0xf);
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                       ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+               } else {
+                       ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               }
+               break;
+       case DB_STENCIL_INFO:
+               track->db_s_info = radeon_get_ib_value(p, idx);
+               break;
+       case DB_DEPTH_VIEW:
+               track->db_depth_view = radeon_get_ib_value(p, idx);
+               break;
+       case DB_DEPTH_SIZE:
+               track->db_depth_size = radeon_get_ib_value(p, idx);
+               track->db_depth_size_idx = idx;
+               break;
+       case DB_Z_READ_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->db_z_read_offset = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->db_z_read_bo = reloc->robj;
+               break;
+       case DB_Z_WRITE_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->db_z_write_offset = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->db_z_write_bo = reloc->robj;
+               break;
+       case DB_STENCIL_READ_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->db_s_read_offset = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->db_s_read_bo = reloc->robj;
+               break;
+       case DB_STENCIL_WRITE_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->db_s_write_offset = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->db_s_write_bo = reloc->robj;
+               break;
+       case VGT_STRMOUT_CONFIG:
+               track->vgt_strmout_config = radeon_get_ib_value(p, idx);
+               break;
+       case VGT_STRMOUT_BUFFER_CONFIG:
+               track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx);
+               break;
+       case CB_TARGET_MASK:
+               track->cb_target_mask = radeon_get_ib_value(p, idx);
+               break;
+       case CB_SHADER_MASK:
+               track->cb_shader_mask = radeon_get_ib_value(p, idx);
+               break;
+       case PA_SC_AA_CONFIG:
+               tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
+               track->nsamples = 1 << tmp;
+               break;
+       case CB_COLOR0_VIEW:
+       case CB_COLOR1_VIEW:
+       case CB_COLOR2_VIEW:
+       case CB_COLOR3_VIEW:
+       case CB_COLOR4_VIEW:
+       case CB_COLOR5_VIEW:
+       case CB_COLOR6_VIEW:
+       case CB_COLOR7_VIEW:
+               tmp = (reg - CB_COLOR0_VIEW) / 0x3c;
+               track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
+               break;
+       case CB_COLOR8_VIEW:
+       case CB_COLOR9_VIEW:
+       case CB_COLOR10_VIEW:
+       case CB_COLOR11_VIEW:
+               tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8;
+               track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
+               break;
+       case CB_COLOR0_INFO:
+       case CB_COLOR1_INFO:
+       case CB_COLOR2_INFO:
+       case CB_COLOR3_INFO:
+       case CB_COLOR4_INFO:
+       case CB_COLOR5_INFO:
+       case CB_COLOR6_INFO:
+       case CB_COLOR7_INFO:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               tmp = (reg - CB_COLOR0_INFO) / 0x3c;
+               track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                       ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+               } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                       ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               }
+               break;
+       case CB_COLOR8_INFO:
+       case CB_COLOR9_INFO:
+       case CB_COLOR10_INFO:
+       case CB_COLOR11_INFO:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
+               track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                       ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+               } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                       ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               }
+               break;
+       case CB_COLOR0_PITCH:
+       case CB_COLOR1_PITCH:
+       case CB_COLOR2_PITCH:
+       case CB_COLOR3_PITCH:
+       case CB_COLOR4_PITCH:
+       case CB_COLOR5_PITCH:
+       case CB_COLOR6_PITCH:
+       case CB_COLOR7_PITCH:
+               tmp = (reg - CB_COLOR0_PITCH) / 0x3c;
+               track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_pitch_idx[tmp] = idx;
+               break;
+       case CB_COLOR8_PITCH:
+       case CB_COLOR9_PITCH:
+       case CB_COLOR10_PITCH:
+       case CB_COLOR11_PITCH:
+               tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8;
+               track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_pitch_idx[tmp] = idx;
+               break;
+       case CB_COLOR0_SLICE:
+       case CB_COLOR1_SLICE:
+       case CB_COLOR2_SLICE:
+       case CB_COLOR3_SLICE:
+       case CB_COLOR4_SLICE:
+       case CB_COLOR5_SLICE:
+       case CB_COLOR6_SLICE:
+       case CB_COLOR7_SLICE:
+               tmp = (reg - CB_COLOR0_SLICE) / 0x3c;
+               track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_slice_idx[tmp] = idx;
+               break;
+       case CB_COLOR8_SLICE:
+       case CB_COLOR9_SLICE:
+       case CB_COLOR10_SLICE:
+       case CB_COLOR11_SLICE:
+               tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8;
+               track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_slice_idx[tmp] = idx;
+               break;
+       case CB_COLOR0_ATTRIB:
+       case CB_COLOR1_ATTRIB:
+       case CB_COLOR2_ATTRIB:
+       case CB_COLOR3_ATTRIB:
+       case CB_COLOR4_ATTRIB:
+       case CB_COLOR5_ATTRIB:
+       case CB_COLOR6_ATTRIB:
+       case CB_COLOR7_ATTRIB:
+       case CB_COLOR8_ATTRIB:
+       case CB_COLOR9_ATTRIB:
+       case CB_COLOR10_ATTRIB:
+       case CB_COLOR11_ATTRIB:
+               break;
+       case CB_COLOR0_DIM:
+       case CB_COLOR1_DIM:
+       case CB_COLOR2_DIM:
+       case CB_COLOR3_DIM:
+       case CB_COLOR4_DIM:
+       case CB_COLOR5_DIM:
+       case CB_COLOR6_DIM:
+       case CB_COLOR7_DIM:
+               tmp = (reg - CB_COLOR0_DIM) / 0x3c;
+               track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_dim_idx[tmp] = idx;
+               break;
+       case CB_COLOR8_DIM:
+       case CB_COLOR9_DIM:
+       case CB_COLOR10_DIM:
+       case CB_COLOR11_DIM:
+               tmp = ((reg - CB_COLOR8_DIM) / 0x1c) + 8;
+               track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_dim_idx[tmp] = idx;
+               break;
+       case CB_COLOR0_FMASK:
+       case CB_COLOR1_FMASK:
+       case CB_COLOR2_FMASK:
+       case CB_COLOR3_FMASK:
+       case CB_COLOR4_FMASK:
+       case CB_COLOR5_FMASK:
+       case CB_COLOR6_FMASK:
+       case CB_COLOR7_FMASK:
+               tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->cb_color_fmask_bo[tmp] = reloc->robj;
+               break;
+       case CB_COLOR0_CMASK:
+       case CB_COLOR1_CMASK:
+       case CB_COLOR2_CMASK:
+       case CB_COLOR3_CMASK:
+       case CB_COLOR4_CMASK:
+       case CB_COLOR5_CMASK:
+       case CB_COLOR6_CMASK:
+       case CB_COLOR7_CMASK:
+               tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->cb_color_cmask_bo[tmp] = reloc->robj;
+               break;
+       case CB_COLOR0_FMASK_SLICE:
+       case CB_COLOR1_FMASK_SLICE:
+       case CB_COLOR2_FMASK_SLICE:
+       case CB_COLOR3_FMASK_SLICE:
+       case CB_COLOR4_FMASK_SLICE:
+       case CB_COLOR5_FMASK_SLICE:
+       case CB_COLOR6_FMASK_SLICE:
+       case CB_COLOR7_FMASK_SLICE:
+               tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c;
+               track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx);
+               break;
+       case CB_COLOR0_CMASK_SLICE:
+       case CB_COLOR1_CMASK_SLICE:
+       case CB_COLOR2_CMASK_SLICE:
+       case CB_COLOR3_CMASK_SLICE:
+       case CB_COLOR4_CMASK_SLICE:
+       case CB_COLOR5_CMASK_SLICE:
+       case CB_COLOR6_CMASK_SLICE:
+       case CB_COLOR7_CMASK_SLICE:
+               tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c;
+               track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx);
+               break;
+       case CB_COLOR0_BASE:
+       case CB_COLOR1_BASE:
+       case CB_COLOR2_BASE:
+       case CB_COLOR3_BASE:
+       case CB_COLOR4_BASE:
+       case CB_COLOR5_BASE:
+       case CB_COLOR6_BASE:
+       case CB_COLOR7_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               tmp = (reg - CB_COLOR0_BASE) / 0x3c;
+               track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->cb_color_base_last[tmp] = ib[idx];
+               track->cb_color_bo[tmp] = reloc->robj;
+               break;
+       case CB_COLOR8_BASE:
+       case CB_COLOR9_BASE:
+       case CB_COLOR10_BASE:
+       case CB_COLOR11_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8;
+               track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->cb_color_base_last[tmp] = ib[idx];
+               track->cb_color_bo[tmp] = reloc->robj;
+               break;
+       case CB_IMMED0_BASE:
+       case CB_IMMED1_BASE:
+       case CB_IMMED2_BASE:
+       case CB_IMMED3_BASE:
+       case CB_IMMED4_BASE:
+       case CB_IMMED5_BASE:
+       case CB_IMMED6_BASE:
+       case CB_IMMED7_BASE:
+       case CB_IMMED8_BASE:
+       case CB_IMMED9_BASE:
+       case CB_IMMED10_BASE:
+       case CB_IMMED11_BASE:
+       case DB_HTILE_DATA_BASE:
+       case SQ_PGM_START_FS:
+       case SQ_PGM_START_ES:
+       case SQ_PGM_START_VS:
+       case SQ_PGM_START_GS:
+       case SQ_PGM_START_PS:
+       case SQ_PGM_START_HS:
+       case SQ_PGM_START_LS:
+       case GDS_ADDR_BASE:
+       case SQ_CONST_MEM_BASE:
+       case SQ_ALU_CONST_CACHE_GS_0:
+       case SQ_ALU_CONST_CACHE_GS_1:
+       case SQ_ALU_CONST_CACHE_GS_2:
+       case SQ_ALU_CONST_CACHE_GS_3:
+       case SQ_ALU_CONST_CACHE_GS_4:
+       case SQ_ALU_CONST_CACHE_GS_5:
+       case SQ_ALU_CONST_CACHE_GS_6:
+       case SQ_ALU_CONST_CACHE_GS_7:
+       case SQ_ALU_CONST_CACHE_GS_8:
+       case SQ_ALU_CONST_CACHE_GS_9:
+       case SQ_ALU_CONST_CACHE_GS_10:
+       case SQ_ALU_CONST_CACHE_GS_11:
+       case SQ_ALU_CONST_CACHE_GS_12:
+       case SQ_ALU_CONST_CACHE_GS_13:
+       case SQ_ALU_CONST_CACHE_GS_14:
+       case SQ_ALU_CONST_CACHE_GS_15:
+       case SQ_ALU_CONST_CACHE_PS_0:
+       case SQ_ALU_CONST_CACHE_PS_1:
+       case SQ_ALU_CONST_CACHE_PS_2:
+       case SQ_ALU_CONST_CACHE_PS_3:
+       case SQ_ALU_CONST_CACHE_PS_4:
+       case SQ_ALU_CONST_CACHE_PS_5:
+       case SQ_ALU_CONST_CACHE_PS_6:
+       case SQ_ALU_CONST_CACHE_PS_7:
+       case SQ_ALU_CONST_CACHE_PS_8:
+       case SQ_ALU_CONST_CACHE_PS_9:
+       case SQ_ALU_CONST_CACHE_PS_10:
+       case SQ_ALU_CONST_CACHE_PS_11:
+       case SQ_ALU_CONST_CACHE_PS_12:
+       case SQ_ALU_CONST_CACHE_PS_13:
+       case SQ_ALU_CONST_CACHE_PS_14:
+       case SQ_ALU_CONST_CACHE_PS_15:
+       case SQ_ALU_CONST_CACHE_VS_0:
+       case SQ_ALU_CONST_CACHE_VS_1:
+       case SQ_ALU_CONST_CACHE_VS_2:
+       case SQ_ALU_CONST_CACHE_VS_3:
+       case SQ_ALU_CONST_CACHE_VS_4:
+       case SQ_ALU_CONST_CACHE_VS_5:
+       case SQ_ALU_CONST_CACHE_VS_6:
+       case SQ_ALU_CONST_CACHE_VS_7:
+       case SQ_ALU_CONST_CACHE_VS_8:
+       case SQ_ALU_CONST_CACHE_VS_9:
+       case SQ_ALU_CONST_CACHE_VS_10:
+       case SQ_ALU_CONST_CACHE_VS_11:
+       case SQ_ALU_CONST_CACHE_VS_12:
+       case SQ_ALU_CONST_CACHE_VS_13:
+       case SQ_ALU_CONST_CACHE_VS_14:
+       case SQ_ALU_CONST_CACHE_VS_15:
+       case SQ_ALU_CONST_CACHE_HS_0:
+       case SQ_ALU_CONST_CACHE_HS_1:
+       case SQ_ALU_CONST_CACHE_HS_2:
+       case SQ_ALU_CONST_CACHE_HS_3:
+       case SQ_ALU_CONST_CACHE_HS_4:
+       case SQ_ALU_CONST_CACHE_HS_5:
+       case SQ_ALU_CONST_CACHE_HS_6:
+       case SQ_ALU_CONST_CACHE_HS_7:
+       case SQ_ALU_CONST_CACHE_HS_8:
+       case SQ_ALU_CONST_CACHE_HS_9:
+       case SQ_ALU_CONST_CACHE_HS_10:
+       case SQ_ALU_CONST_CACHE_HS_11:
+       case SQ_ALU_CONST_CACHE_HS_12:
+       case SQ_ALU_CONST_CACHE_HS_13:
+       case SQ_ALU_CONST_CACHE_HS_14:
+       case SQ_ALU_CONST_CACHE_HS_15:
+       case SQ_ALU_CONST_CACHE_LS_0:
+       case SQ_ALU_CONST_CACHE_LS_1:
+       case SQ_ALU_CONST_CACHE_LS_2:
+       case SQ_ALU_CONST_CACHE_LS_3:
+       case SQ_ALU_CONST_CACHE_LS_4:
+       case SQ_ALU_CONST_CACHE_LS_5:
+       case SQ_ALU_CONST_CACHE_LS_6:
+       case SQ_ALU_CONST_CACHE_LS_7:
+       case SQ_ALU_CONST_CACHE_LS_8:
+       case SQ_ALU_CONST_CACHE_LS_9:
+       case SQ_ALU_CONST_CACHE_LS_10:
+       case SQ_ALU_CONST_CACHE_LS_11:
+       case SQ_ALU_CONST_CACHE_LS_12:
+       case SQ_ALU_CONST_CACHE_LS_13:
+       case SQ_ALU_CONST_CACHE_LS_14:
+       case SQ_ALU_CONST_CACHE_LS_15:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               break;
+       default:
+               dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * evergreen_check_texture_resource() - check if register is authorized or not
+ * @p: parser structure holding parsing context
+ * @idx: index into the cs buffer
+ * @texture: texture's bo structure
+ * @mipmap: mipmap's bo structure
+ *
+ * This function will check that the resource has valid field and that
+ * the texture and mipmap bo object are big enough to cover this resource.
+ */
+static inline int evergreen_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
+                                                  struct radeon_bo *texture,
+                                                  struct radeon_bo *mipmap)
+{
+       /* XXX fill in */
+       return 0;
+}
+
+static int evergreen_packet3_check(struct radeon_cs_parser *p,
+                                  struct radeon_cs_packet *pkt)
+{
+       struct radeon_cs_reloc *reloc;
+       struct evergreen_cs_track *track;
+       volatile u32 *ib;
+       unsigned idx;
+       unsigned i;
+       unsigned start_reg, end_reg, reg;
+       int r;
+       u32 idx_value;
+
+       track = (struct evergreen_cs_track *)p->track;
+       ib = p->ib->ptr;
+       idx = pkt->idx + 1;
+       idx_value = radeon_get_ib_value(p, idx);
+
+       switch (pkt->opcode) {
+       case PACKET3_CONTEXT_CONTROL:
+               if (pkt->count != 1) {
+                       DRM_ERROR("bad CONTEXT_CONTROL\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_INDEX_TYPE:
+       case PACKET3_NUM_INSTANCES:
+       case PACKET3_CLEAR_STATE:
+               if (pkt->count) {
+                       DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_INDEX_BASE:
+               if (pkt->count != 1) {
+                       DRM_ERROR("bad INDEX_BASE\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad INDEX_BASE\n");
+                       return -EINVAL;
+               }
+               ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+               ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX:
+               if (pkt->count != 3) {
+                       DRM_ERROR("bad DRAW_INDEX\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad DRAW_INDEX\n");
+                       return -EINVAL;
+               }
+               ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+               ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_2:
+               if (pkt->count != 4) {
+                       DRM_ERROR("bad DRAW_INDEX_2\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad DRAW_INDEX_2\n");
+                       return -EINVAL;
+               }
+               ib[idx+1] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+               ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_AUTO:
+               if (pkt->count != 1) {
+                       DRM_ERROR("bad DRAW_INDEX_AUTO\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_MULTI_AUTO:
+               if (pkt->count != 2) {
+                       DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_IMMD:
+               if (pkt->count < 2) {
+                       DRM_ERROR("bad DRAW_INDEX_IMMD\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_OFFSET:
+               if (pkt->count != 2) {
+                       DRM_ERROR("bad DRAW_INDEX_OFFSET\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_OFFSET_2:
+               if (pkt->count != 3) {
+                       DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_WAIT_REG_MEM:
+               if (pkt->count != 5) {
+                       DRM_ERROR("bad WAIT_REG_MEM\n");
+                       return -EINVAL;
+               }
+               /* bit 4 is reg (0) or mem (1) */
+               if (idx_value & 0x10) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("bad WAIT_REG_MEM\n");
+                               return -EINVAL;
+                       }
+                       ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+                       ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               }
+               break;
+       case PACKET3_SURFACE_SYNC:
+               if (pkt->count != 3) {
+                       DRM_ERROR("bad SURFACE_SYNC\n");
+                       return -EINVAL;
+               }
+               /* 0xffffffff/0x0 is flush all cache flag */
+               if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
+                   radeon_get_ib_value(p, idx + 2) != 0) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("bad SURFACE_SYNC\n");
+                               return -EINVAL;
+                       }
+                       ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               }
+               break;
+       case PACKET3_EVENT_WRITE:
+               if (pkt->count != 2 && pkt->count != 0) {
+                       DRM_ERROR("bad EVENT_WRITE\n");
+                       return -EINVAL;
+               }
+               if (pkt->count) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("bad EVENT_WRITE\n");
+                               return -EINVAL;
+                       }
+                       ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+                       ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               }
+               break;
+       case PACKET3_EVENT_WRITE_EOP:
+               if (pkt->count != 4) {
+                       DRM_ERROR("bad EVENT_WRITE_EOP\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad EVENT_WRITE_EOP\n");
+                       return -EINVAL;
+               }
+               ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+               ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               break;
+       case PACKET3_EVENT_WRITE_EOS:
+               if (pkt->count != 3) {
+                       DRM_ERROR("bad EVENT_WRITE_EOS\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad EVENT_WRITE_EOS\n");
+                       return -EINVAL;
+               }
+               ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+               ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               break;
+       case PACKET3_SET_CONFIG_REG:
+               start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
+                   (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
+                   (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
+                       DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
+                       return -EINVAL;
+               }
+               for (i = 0; i < pkt->count; i++) {
+                       reg = start_reg + (4 * i);
+                       r = evergreen_cs_check_reg(p, reg, idx+1+i);
+                       if (r)
+                               return r;
+               }
+               break;
+       case PACKET3_SET_CONTEXT_REG:
+               start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_CONTEXT_REG_START) ||
+                   (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
+                   (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
+                       DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
+                       return -EINVAL;
+               }
+               for (i = 0; i < pkt->count; i++) {
+                       reg = start_reg + (4 * i);
+                       r = evergreen_cs_check_reg(p, reg, idx+1+i);
+                       if (r)
+                               return r;
+               }
+               break;
+       case PACKET3_SET_RESOURCE:
+               if (pkt->count % 8) {
+                       DRM_ERROR("bad SET_RESOURCE\n");
+                       return -EINVAL;
+               }
+               start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_RESOURCE_START) ||
+                   (start_reg >= PACKET3_SET_RESOURCE_END) ||
+                   (end_reg >= PACKET3_SET_RESOURCE_END)) {
+                       DRM_ERROR("bad SET_RESOURCE\n");
+                       return -EINVAL;
+               }
+               for (i = 0; i < (pkt->count / 8); i++) {
+                       struct radeon_bo *texture, *mipmap;
+                       u32 size, offset;
+
+                       switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
+                       case SQ_TEX_VTX_VALID_TEXTURE:
+                               /* tex base */
+                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               if (r) {
+                                       DRM_ERROR("bad SET_RESOURCE (tex)\n");
+                                       return -EINVAL;
+                               }
+                               ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+                               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                                       ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                                       ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               texture = reloc->robj;
+                               /* tex mip base */
+                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               if (r) {
+                                       DRM_ERROR("bad SET_RESOURCE (tex)\n");
+                                       return -EINVAL;
+                               }
+                               ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+                               mipmap = reloc->robj;
+                               r = evergreen_check_texture_resource(p,  idx+1+(i*8),
+                                               texture, mipmap);
+                               if (r)
+                                       return r;
+                               break;
+                       case SQ_TEX_VTX_VALID_BUFFER:
+                               /* vtx base */
+                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               if (r) {
+                                       DRM_ERROR("bad SET_RESOURCE (vtx)\n");
+                                       return -EINVAL;
+                               }
+                               offset = radeon_get_ib_value(p, idx+1+(i*8)+0);
+                               size = radeon_get_ib_value(p, idx+1+(i*8)+1);
+                               if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
+                                       /* force size to size of the buffer */
+                                       dev_warn(p->dev, "vbo resource seems too big for the bo\n");
+                                       ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj);
+                               }
+                               ib[idx+1+(i*8)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
+                               ib[idx+1+(i*8)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+                               break;
+                       case SQ_TEX_VTX_INVALID_TEXTURE:
+                       case SQ_TEX_VTX_INVALID_BUFFER:
+                       default:
+                               DRM_ERROR("bad SET_RESOURCE\n");
+                               return -EINVAL;
+                       }
+               }
+               break;
+       case PACKET3_SET_ALU_CONST:
+               /* XXX fix me ALU const buffers only */
+               break;
+       case PACKET3_SET_BOOL_CONST:
+               start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_BOOL_CONST_START) ||
+                   (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
+                   (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
+                       DRM_ERROR("bad SET_BOOL_CONST\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_SET_LOOP_CONST:
+               start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_LOOP_CONST_START) ||
+                   (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
+                   (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
+                       DRM_ERROR("bad SET_LOOP_CONST\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_SET_CTL_CONST:
+               start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_CTL_CONST_START) ||
+                   (start_reg >= PACKET3_SET_CTL_CONST_END) ||
+                   (end_reg >= PACKET3_SET_CTL_CONST_END)) {
+                       DRM_ERROR("bad SET_CTL_CONST\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_SET_SAMPLER:
+               if (pkt->count % 3) {
+                       DRM_ERROR("bad SET_SAMPLER\n");
+                       return -EINVAL;
+               }
+               start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_SAMPLER_START) ||
+                   (start_reg >= PACKET3_SET_SAMPLER_END) ||
+                   (end_reg >= PACKET3_SET_SAMPLER_END)) {
+                       DRM_ERROR("bad SET_SAMPLER\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_NOP:
+               break;
+       default:
+               DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+int evergreen_cs_parse(struct radeon_cs_parser *p)
+{
+       struct radeon_cs_packet pkt;
+       struct evergreen_cs_track *track;
+       int r;
+
+       if (p->track == NULL) {
+               /* initialize tracker, we are in kms */
+               track = kzalloc(sizeof(*track), GFP_KERNEL);
+               if (track == NULL)
+                       return -ENOMEM;
+               evergreen_cs_track_init(track);
+               track->npipes = p->rdev->config.evergreen.tiling_npipes;
+               track->nbanks = p->rdev->config.evergreen.tiling_nbanks;
+               track->group_size = p->rdev->config.evergreen.tiling_group_size;
+               p->track = track;
+       }
+       do {
+               r = evergreen_cs_packet_parse(p, &pkt, p->idx);
+               if (r) {
+                       kfree(p->track);
+                       p->track = NULL;
+                       return r;
+               }
+               p->idx += pkt.count + 2;
+               switch (pkt.type) {
+               case PACKET_TYPE0:
+                       r = evergreen_cs_parse_packet0(p, &pkt);
+                       break;
+               case PACKET_TYPE2:
+                       break;
+               case PACKET_TYPE3:
+                       r = evergreen_packet3_check(p, &pkt);
+                       break;
+               default:
+                       DRM_ERROR("Unknown packet type %d !\n", pkt.type);
+                       kfree(p->track);
+                       p->track = NULL;
+                       return -EINVAL;
+               }
+               if (r) {
+                       kfree(p->track);
+                       p->track = NULL;
+                       return r;
+               }
+       } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
+#if 0
+       for (r = 0; r < p->ib->length_dw; r++) {
+               printk(KERN_INFO "%05d  0x%08X\n", r, p->ib->ptr[r]);
+               mdelay(1);
+       }
+#endif
+       kfree(p->track);
+       p->track = NULL;
+       return 0;
+}
+
index af86af836f13dcb446d78418c65f3c6c69a2660f..e028c1cd9d9b7732d8eeaf1c8773df35e13c93fa 100644 (file)
 #define EVERGREEN_DATA_FORMAT                           0x6b00
 #       define EVERGREEN_INTERLEAVE_EN                  (1 << 0)
 #define EVERGREEN_DESKTOP_HEIGHT                        0x6b04
+#define EVERGREEN_VLINE_START_END                       0x6b08
+#define EVERGREEN_VLINE_STATUS                          0x6bb8
+#       define EVERGREEN_VLINE_STAT                     (1 << 12)
 
 #define EVERGREEN_VIEWPORT_START                        0x6d70
 #define EVERGREEN_VIEWPORT_SIZE                         0x6d74
index 93e9e17ad54ad4a1717738489cad54caaf47bb17..a1cd621780e21bc5fdd7251c397dfc362d3c5ec3 100644 (file)
 #define                CLIP_VTX_REORDER_ENA                            (1 << 0)
 #define                NUM_CLIP_SEQ(x)                                 ((x) << 1)
 #define PA_SC_AA_CONFIG                                        0x28C04
+#define         MSAA_NUM_SAMPLES_SHIFT                  0
+#define         MSAA_NUM_SAMPLES_MASK                   0x3
 #define PA_SC_CLIPRECT_RULE                            0x2820C
 #define        PA_SC_EDGERULE                                  0x28230
 #define        PA_SC_FIFO_SIZE                                 0x8BCC
 #       define DC_HPDx_RX_INT_TIMER(x)                    ((x) << 16)
 #       define DC_HPDx_EN                                 (1 << 28)
 
+/*
+ * PM4
+ */
+#define        PACKET_TYPE0    0
+#define        PACKET_TYPE1    1
+#define        PACKET_TYPE2    2
+#define        PACKET_TYPE3    3
+
+#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
+#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
+#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2)
+#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
+#define PACKET0(reg, n)        ((PACKET_TYPE0 << 30) |                         \
+                        (((reg) >> 2) & 0xFFFF) |                      \
+                        ((n) & 0x3FFF) << 16)
+#define CP_PACKET2                     0x80000000
+#define                PACKET2_PAD_SHIFT               0
+#define                PACKET2_PAD_MASK                (0x3fffffff << 0)
+
+#define PACKET2(v)     (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
+
+#define PACKET3(op, n) ((PACKET_TYPE3 << 30) |                         \
+                        (((op) & 0xFF) << 8) |                         \
+                        ((n) & 0x3FFF) << 16)
+
+/* Packet 3 types */
+#define        PACKET3_NOP                                     0x10
+#define        PACKET3_SET_BASE                                0x11
+#define        PACKET3_CLEAR_STATE                             0x12
+#define        PACKET3_INDIRECT_BUFFER_SIZE                    0x13
+#define        PACKET3_DISPATCH_DIRECT                         0x15
+#define        PACKET3_DISPATCH_INDIRECT                       0x16
+#define        PACKET3_INDIRECT_BUFFER_END                     0x17
+#define        PACKET3_SET_PREDICATION                         0x20
+#define        PACKET3_REG_RMW                                 0x21
+#define        PACKET3_COND_EXEC                               0x22
+#define        PACKET3_PRED_EXEC                               0x23
+#define        PACKET3_DRAW_INDIRECT                           0x24
+#define        PACKET3_DRAW_INDEX_INDIRECT                     0x25
+#define        PACKET3_INDEX_BASE                              0x26
+#define        PACKET3_DRAW_INDEX_2                            0x27
+#define        PACKET3_CONTEXT_CONTROL                         0x28
+#define        PACKET3_DRAW_INDEX_OFFSET                       0x29
+#define        PACKET3_INDEX_TYPE                              0x2A
+#define        PACKET3_DRAW_INDEX                              0x2B
+#define        PACKET3_DRAW_INDEX_AUTO                         0x2D
+#define        PACKET3_DRAW_INDEX_IMMD                         0x2E
+#define        PACKET3_NUM_INSTANCES                           0x2F
+#define        PACKET3_DRAW_INDEX_MULTI_AUTO                   0x30
+#define        PACKET3_STRMOUT_BUFFER_UPDATE                   0x34
+#define        PACKET3_DRAW_INDEX_OFFSET_2                     0x35
+#define        PACKET3_DRAW_INDEX_MULTI_ELEMENT                0x36
+#define        PACKET3_MEM_SEMAPHORE                           0x39
+#define        PACKET3_MPEG_INDEX                              0x3A
+#define        PACKET3_WAIT_REG_MEM                            0x3C
+#define        PACKET3_MEM_WRITE                               0x3D
+#define        PACKET3_INDIRECT_BUFFER                         0x32
+#define        PACKET3_SURFACE_SYNC                            0x43
+#              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
+#              define PACKET3_CB1_DEST_BASE_ENA    (1 << 7)
+#              define PACKET3_CB2_DEST_BASE_ENA    (1 << 8)
+#              define PACKET3_CB3_DEST_BASE_ENA    (1 << 9)
+#              define PACKET3_CB4_DEST_BASE_ENA    (1 << 10)
+#              define PACKET3_CB5_DEST_BASE_ENA    (1 << 11)
+#              define PACKET3_CB6_DEST_BASE_ENA    (1 << 12)
+#              define PACKET3_CB7_DEST_BASE_ENA    (1 << 13)
+#              define PACKET3_DB_DEST_BASE_ENA     (1 << 14)
+#              define PACKET3_CB8_DEST_BASE_ENA    (1 << 15)
+#              define PACKET3_CB9_DEST_BASE_ENA    (1 << 16)
+#              define PACKET3_CB10_DEST_BASE_ENA   (1 << 17)
+#              define PACKET3_CB11_DEST_BASE_ENA   (1 << 17)
+#              define PACKET3_FULL_CACHE_ENA       (1 << 20)
+#              define PACKET3_TC_ACTION_ENA        (1 << 23)
+#              define PACKET3_VC_ACTION_ENA        (1 << 24)
+#              define PACKET3_CB_ACTION_ENA        (1 << 25)
+#              define PACKET3_DB_ACTION_ENA        (1 << 26)
+#              define PACKET3_SH_ACTION_ENA        (1 << 27)
+#              define PACKET3_SMX_ACTION_ENA       (1 << 28)
+#define        PACKET3_ME_INITIALIZE                           0x44
+#define                PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
+#define        PACKET3_COND_WRITE                              0x45
+#define        PACKET3_EVENT_WRITE                             0x46
+#define        PACKET3_EVENT_WRITE_EOP                         0x47
+#define        PACKET3_EVENT_WRITE_EOS                         0x48
+#define        PACKET3_PREAMBLE_CNTL                           0x4A
+#define        PACKET3_RB_OFFSET                               0x4B
+#define        PACKET3_ALU_PS_CONST_BUFFER_COPY                0x4C
+#define        PACKET3_ALU_VS_CONST_BUFFER_COPY                0x4D
+#define        PACKET3_ALU_PS_CONST_UPDATE                     0x4E
+#define        PACKET3_ALU_VS_CONST_UPDATE                     0x4F
+#define        PACKET3_ONE_REG_WRITE                           0x57
+#define        PACKET3_SET_CONFIG_REG                          0x68
+#define                PACKET3_SET_CONFIG_REG_START                    0x00008000
+#define                PACKET3_SET_CONFIG_REG_END                      0x0000ac00
+#define        PACKET3_SET_CONTEXT_REG                         0x69
+#define                PACKET3_SET_CONTEXT_REG_START                   0x00028000
+#define                PACKET3_SET_CONTEXT_REG_END                     0x00029000
+#define        PACKET3_SET_ALU_CONST                           0x6A
+/* alu const buffers only; no reg file */
+#define        PACKET3_SET_BOOL_CONST                          0x6B
+#define                PACKET3_SET_BOOL_CONST_START                    0x0003a500
+#define                PACKET3_SET_BOOL_CONST_END                      0x0003a518
+#define        PACKET3_SET_LOOP_CONST                          0x6C
+#define                PACKET3_SET_LOOP_CONST_START                    0x0003a200
+#define                PACKET3_SET_LOOP_CONST_END                      0x0003a500
+#define        PACKET3_SET_RESOURCE                            0x6D
+#define                PACKET3_SET_RESOURCE_START                      0x00030000
+#define                PACKET3_SET_RESOURCE_END                        0x00038000
+#define        PACKET3_SET_SAMPLER                             0x6E
+#define                PACKET3_SET_SAMPLER_START                       0x0003c000
+#define                PACKET3_SET_SAMPLER_END                         0x0003c600
+#define        PACKET3_SET_CTL_CONST                           0x6F
+#define                PACKET3_SET_CTL_CONST_START                     0x0003cff0
+#define                PACKET3_SET_CTL_CONST_END                       0x0003ff0c
+#define        PACKET3_SET_RESOURCE_OFFSET                     0x70
+#define        PACKET3_SET_ALU_CONST_VS                        0x71
+#define        PACKET3_SET_ALU_CONST_DI                        0x72
+#define        PACKET3_SET_CONTEXT_REG_INDIRECT                0x73
+#define        PACKET3_SET_RESOURCE_INDIRECT                   0x74
+#define        PACKET3_SET_APPEND_CNT                          0x75
+
+#define        SQ_RESOURCE_CONSTANT_WORD7_0                            0x3001c
+#define                S__SQ_CONSTANT_TYPE(x)                  (((x) & 3) << 30)
+#define                G__SQ_CONSTANT_TYPE(x)                  (((x) >> 30) & 3)
+#define                        SQ_TEX_VTX_INVALID_TEXTURE                      0x0
+#define                        SQ_TEX_VTX_INVALID_BUFFER                       0x1
+#define                        SQ_TEX_VTX_VALID_TEXTURE                        0x2
+#define                        SQ_TEX_VTX_VALID_BUFFER                         0x3
+
+#define SQ_CONST_MEM_BASE                              0x8df8
+
+#define SQ_ESGS_RING_SIZE                              0x8c44
+#define SQ_GSVS_RING_SIZE                              0x8c4c
+#define SQ_ESTMP_RING_SIZE                             0x8c54
+#define SQ_GSTMP_RING_SIZE                             0x8c5c
+#define SQ_VSTMP_RING_SIZE                             0x8c64
+#define SQ_PSTMP_RING_SIZE                             0x8c6c
+#define SQ_LSTMP_RING_SIZE                             0x8e14
+#define SQ_HSTMP_RING_SIZE                             0x8e1c
+#define VGT_TF_RING_SIZE                               0x8988
+
+#define SQ_ESGS_RING_ITEMSIZE                          0x28900
+#define SQ_GSVS_RING_ITEMSIZE                          0x28904
+#define SQ_ESTMP_RING_ITEMSIZE                         0x28908
+#define SQ_GSTMP_RING_ITEMSIZE                         0x2890c
+#define SQ_VSTMP_RING_ITEMSIZE                         0x28910
+#define SQ_PSTMP_RING_ITEMSIZE                         0x28914
+#define SQ_LSTMP_RING_ITEMSIZE                         0x28830
+#define SQ_HSTMP_RING_ITEMSIZE                         0x28834
+
+#define SQ_GS_VERT_ITEMSIZE                            0x2891c
+#define SQ_GS_VERT_ITEMSIZE_1                          0x28920
+#define SQ_GS_VERT_ITEMSIZE_2                          0x28924
+#define SQ_GS_VERT_ITEMSIZE_3                          0x28928
+#define SQ_GSVS_RING_OFFSET_1                          0x2892c
+#define SQ_GSVS_RING_OFFSET_2                          0x28930
+#define SQ_GSVS_RING_OFFSET_3                          0x28934
+
+#define SQ_ALU_CONST_BUFFER_SIZE_PS_0                  0x28140
+#define SQ_ALU_CONST_BUFFER_SIZE_HS_0                  0x28f80
+
+#define SQ_ALU_CONST_CACHE_PS_0                                0x28940
+#define SQ_ALU_CONST_CACHE_PS_1                                0x28944
+#define SQ_ALU_CONST_CACHE_PS_2                                0x28948
+#define SQ_ALU_CONST_CACHE_PS_3                                0x2894c
+#define SQ_ALU_CONST_CACHE_PS_4                                0x28950
+#define SQ_ALU_CONST_CACHE_PS_5                                0x28954
+#define SQ_ALU_CONST_CACHE_PS_6                                0x28958
+#define SQ_ALU_CONST_CACHE_PS_7                                0x2895c
+#define SQ_ALU_CONST_CACHE_PS_8                                0x28960
+#define SQ_ALU_CONST_CACHE_PS_9                                0x28964
+#define SQ_ALU_CONST_CACHE_PS_10                       0x28968
+#define SQ_ALU_CONST_CACHE_PS_11                       0x2896c
+#define SQ_ALU_CONST_CACHE_PS_12                       0x28970
+#define SQ_ALU_CONST_CACHE_PS_13                       0x28974
+#define SQ_ALU_CONST_CACHE_PS_14                       0x28978
+#define SQ_ALU_CONST_CACHE_PS_15                       0x2897c
+#define SQ_ALU_CONST_CACHE_VS_0                                0x28980
+#define SQ_ALU_CONST_CACHE_VS_1                                0x28984
+#define SQ_ALU_CONST_CACHE_VS_2                                0x28988
+#define SQ_ALU_CONST_CACHE_VS_3                                0x2898c
+#define SQ_ALU_CONST_CACHE_VS_4                                0x28990
+#define SQ_ALU_CONST_CACHE_VS_5                                0x28994
+#define SQ_ALU_CONST_CACHE_VS_6                                0x28998
+#define SQ_ALU_CONST_CACHE_VS_7                                0x2899c
+#define SQ_ALU_CONST_CACHE_VS_8                                0x289a0
+#define SQ_ALU_CONST_CACHE_VS_9                                0x289a4
+#define SQ_ALU_CONST_CACHE_VS_10                       0x289a8
+#define SQ_ALU_CONST_CACHE_VS_11                       0x289ac
+#define SQ_ALU_CONST_CACHE_VS_12                       0x289b0
+#define SQ_ALU_CONST_CACHE_VS_13                       0x289b4
+#define SQ_ALU_CONST_CACHE_VS_14                       0x289b8
+#define SQ_ALU_CONST_CACHE_VS_15                       0x289bc
+#define SQ_ALU_CONST_CACHE_GS_0                                0x289c0
+#define SQ_ALU_CONST_CACHE_GS_1                                0x289c4
+#define SQ_ALU_CONST_CACHE_GS_2                                0x289c8
+#define SQ_ALU_CONST_CACHE_GS_3                                0x289cc
+#define SQ_ALU_CONST_CACHE_GS_4                                0x289d0
+#define SQ_ALU_CONST_CACHE_GS_5                                0x289d4
+#define SQ_ALU_CONST_CACHE_GS_6                                0x289d8
+#define SQ_ALU_CONST_CACHE_GS_7                                0x289dc
+#define SQ_ALU_CONST_CACHE_GS_8                                0x289e0
+#define SQ_ALU_CONST_CACHE_GS_9                                0x289e4
+#define SQ_ALU_CONST_CACHE_GS_10                       0x289e8
+#define SQ_ALU_CONST_CACHE_GS_11                       0x289ec
+#define SQ_ALU_CONST_CACHE_GS_12                       0x289f0
+#define SQ_ALU_CONST_CACHE_GS_13                       0x289f4
+#define SQ_ALU_CONST_CACHE_GS_14                       0x289f8
+#define SQ_ALU_CONST_CACHE_GS_15                       0x289fc
+#define SQ_ALU_CONST_CACHE_HS_0                                0x28f00
+#define SQ_ALU_CONST_CACHE_HS_1                                0x28f04
+#define SQ_ALU_CONST_CACHE_HS_2                                0x28f08
+#define SQ_ALU_CONST_CACHE_HS_3                                0x28f0c
+#define SQ_ALU_CONST_CACHE_HS_4                                0x28f10
+#define SQ_ALU_CONST_CACHE_HS_5                                0x28f14
+#define SQ_ALU_CONST_CACHE_HS_6                                0x28f18
+#define SQ_ALU_CONST_CACHE_HS_7                                0x28f1c
+#define SQ_ALU_CONST_CACHE_HS_8                                0x28f20
+#define SQ_ALU_CONST_CACHE_HS_9                                0x28f24
+#define SQ_ALU_CONST_CACHE_HS_10                       0x28f28
+#define SQ_ALU_CONST_CACHE_HS_11                       0x28f2c
+#define SQ_ALU_CONST_CACHE_HS_12                       0x28f30
+#define SQ_ALU_CONST_CACHE_HS_13                       0x28f34
+#define SQ_ALU_CONST_CACHE_HS_14                       0x28f38
+#define SQ_ALU_CONST_CACHE_HS_15                       0x28f3c
+#define SQ_ALU_CONST_CACHE_LS_0                                0x28f40
+#define SQ_ALU_CONST_CACHE_LS_1                                0x28f44
+#define SQ_ALU_CONST_CACHE_LS_2                                0x28f48
+#define SQ_ALU_CONST_CACHE_LS_3                                0x28f4c
+#define SQ_ALU_CONST_CACHE_LS_4                                0x28f50
+#define SQ_ALU_CONST_CACHE_LS_5                                0x28f54
+#define SQ_ALU_CONST_CACHE_LS_6                                0x28f58
+#define SQ_ALU_CONST_CACHE_LS_7                                0x28f5c
+#define SQ_ALU_CONST_CACHE_LS_8                                0x28f60
+#define SQ_ALU_CONST_CACHE_LS_9                                0x28f64
+#define SQ_ALU_CONST_CACHE_LS_10                       0x28f68
+#define SQ_ALU_CONST_CACHE_LS_11                       0x28f6c
+#define SQ_ALU_CONST_CACHE_LS_12                       0x28f70
+#define SQ_ALU_CONST_CACHE_LS_13                       0x28f74
+#define SQ_ALU_CONST_CACHE_LS_14                       0x28f78
+#define SQ_ALU_CONST_CACHE_LS_15                       0x28f7c
+
+#define DB_DEPTH_CONTROL                               0x28800
+#define DB_DEPTH_VIEW                                  0x28008
+#define DB_HTILE_DATA_BASE                             0x28014
+#define DB_Z_INFO                                      0x28040
+#       define Z_ARRAY_MODE(x)                          ((x) << 4)
+#define DB_STENCIL_INFO                                        0x28044
+#define DB_Z_READ_BASE                                 0x28048
+#define DB_STENCIL_READ_BASE                           0x2804c
+#define DB_Z_WRITE_BASE                                        0x28050
+#define DB_STENCIL_WRITE_BASE                          0x28054
+#define DB_DEPTH_SIZE                                  0x28058
+
+#define SQ_PGM_START_PS                                        0x28840
+#define SQ_PGM_START_VS                                        0x2885c
+#define SQ_PGM_START_GS                                        0x28874
+#define SQ_PGM_START_ES                                        0x2888c
+#define SQ_PGM_START_FS                                        0x288a4
+#define SQ_PGM_START_HS                                        0x288b8
+#define SQ_PGM_START_LS                                        0x288d0
+
+#define VGT_STRMOUT_CONFIG                             0x28b94
+#define VGT_STRMOUT_BUFFER_CONFIG                      0x28b98
+
+#define CB_TARGET_MASK                                 0x28238
+#define CB_SHADER_MASK                                 0x2823c
+
+#define GDS_ADDR_BASE                                  0x28720
+
+#define        CB_IMMED0_BASE                                  0x28b9c
+#define        CB_IMMED1_BASE                                  0x28ba0
+#define        CB_IMMED2_BASE                                  0x28ba4
+#define        CB_IMMED3_BASE                                  0x28ba8
+#define        CB_IMMED4_BASE                                  0x28bac
+#define        CB_IMMED5_BASE                                  0x28bb0
+#define        CB_IMMED6_BASE                                  0x28bb4
+#define        CB_IMMED7_BASE                                  0x28bb8
+#define        CB_IMMED8_BASE                                  0x28bbc
+#define        CB_IMMED9_BASE                                  0x28bc0
+#define        CB_IMMED10_BASE                                 0x28bc4
+#define        CB_IMMED11_BASE                                 0x28bc8
+
+/* all 12 CB blocks have these regs */
+#define        CB_COLOR0_BASE                                  0x28c60
+#define        CB_COLOR0_PITCH                                 0x28c64
+#define        CB_COLOR0_SLICE                                 0x28c68
+#define        CB_COLOR0_VIEW                                  0x28c6c
+#define        CB_COLOR0_INFO                                  0x28c70
+#       define CB_ARRAY_MODE(x)                         ((x) << 8)
+#       define ARRAY_LINEAR_GENERAL                     0
+#       define ARRAY_LINEAR_ALIGNED                     1
+#       define ARRAY_1D_TILED_THIN1                     2
+#       define ARRAY_2D_TILED_THIN1                     4
+#define        CB_COLOR0_ATTRIB                                0x28c74
+#define        CB_COLOR0_DIM                                   0x28c78
+/* only CB0-7 blocks have these regs */
+#define        CB_COLOR0_CMASK                                 0x28c7c
+#define        CB_COLOR0_CMASK_SLICE                           0x28c80
+#define        CB_COLOR0_FMASK                                 0x28c84
+#define        CB_COLOR0_FMASK_SLICE                           0x28c88
+#define        CB_COLOR0_CLEAR_WORD0                           0x28c8c
+#define        CB_COLOR0_CLEAR_WORD1                           0x28c90
+#define        CB_COLOR0_CLEAR_WORD2                           0x28c94
+#define        CB_COLOR0_CLEAR_WORD3                           0x28c98
+
+#define        CB_COLOR1_BASE                                  0x28c9c
+#define        CB_COLOR2_BASE                                  0x28cd8
+#define        CB_COLOR3_BASE                                  0x28d14
+#define        CB_COLOR4_BASE                                  0x28d50
+#define        CB_COLOR5_BASE                                  0x28d8c
+#define        CB_COLOR6_BASE                                  0x28dc8
+#define        CB_COLOR7_BASE                                  0x28e04
+#define        CB_COLOR8_BASE                                  0x28e40
+#define        CB_COLOR9_BASE                                  0x28e5c
+#define        CB_COLOR10_BASE                                 0x28e78
+#define        CB_COLOR11_BASE                                 0x28e94
+
+#define        CB_COLOR1_PITCH                                 0x28ca0
+#define        CB_COLOR2_PITCH                                 0x28cdc
+#define        CB_COLOR3_PITCH                                 0x28d18
+#define        CB_COLOR4_PITCH                                 0x28d54
+#define        CB_COLOR5_PITCH                                 0x28d90
+#define        CB_COLOR6_PITCH                                 0x28dcc
+#define        CB_COLOR7_PITCH                                 0x28e08
+#define        CB_COLOR8_PITCH                                 0x28e44
+#define        CB_COLOR9_PITCH                                 0x28e60
+#define        CB_COLOR10_PITCH                                0x28e7c
+#define        CB_COLOR11_PITCH                                0x28e98
+
+#define        CB_COLOR1_SLICE                                 0x28ca4
+#define        CB_COLOR2_SLICE                                 0x28ce0
+#define        CB_COLOR3_SLICE                                 0x28d1c
+#define        CB_COLOR4_SLICE                                 0x28d58
+#define        CB_COLOR5_SLICE                                 0x28d94
+#define        CB_COLOR6_SLICE                                 0x28dd0
+#define        CB_COLOR7_SLICE                                 0x28e0c
+#define        CB_COLOR8_SLICE                                 0x28e48
+#define        CB_COLOR9_SLICE                                 0x28e64
+#define        CB_COLOR10_SLICE                                0x28e80
+#define        CB_COLOR11_SLICE                                0x28e9c
+
+#define        CB_COLOR1_VIEW                                  0x28ca8
+#define        CB_COLOR2_VIEW                                  0x28ce4
+#define        CB_COLOR3_VIEW                                  0x28d20
+#define        CB_COLOR4_VIEW                                  0x28d5c
+#define        CB_COLOR5_VIEW                                  0x28d98
+#define        CB_COLOR6_VIEW                                  0x28dd4
+#define        CB_COLOR7_VIEW                                  0x28e10
+#define        CB_COLOR8_VIEW                                  0x28e4c
+#define        CB_COLOR9_VIEW                                  0x28e68
+#define        CB_COLOR10_VIEW                                 0x28e84
+#define        CB_COLOR11_VIEW                                 0x28ea0
+
+#define        CB_COLOR1_INFO                                  0x28cac
+#define        CB_COLOR2_INFO                                  0x28ce8
+#define        CB_COLOR3_INFO                                  0x28d24
+#define        CB_COLOR4_INFO                                  0x28d60
+#define        CB_COLOR5_INFO                                  0x28d9c
+#define        CB_COLOR6_INFO                                  0x28dd8
+#define        CB_COLOR7_INFO                                  0x28e14
+#define        CB_COLOR8_INFO                                  0x28e50
+#define        CB_COLOR9_INFO                                  0x28e6c
+#define        CB_COLOR10_INFO                                 0x28e88
+#define        CB_COLOR11_INFO                                 0x28ea4
+
+#define        CB_COLOR1_ATTRIB                                0x28cb0
+#define        CB_COLOR2_ATTRIB                                0x28cec
+#define        CB_COLOR3_ATTRIB                                0x28d28
+#define        CB_COLOR4_ATTRIB                                0x28d64
+#define        CB_COLOR5_ATTRIB                                0x28da0
+#define        CB_COLOR6_ATTRIB                                0x28ddc
+#define        CB_COLOR7_ATTRIB                                0x28e18
+#define        CB_COLOR8_ATTRIB                                0x28e54
+#define        CB_COLOR9_ATTRIB                                0x28e70
+#define        CB_COLOR10_ATTRIB                               0x28e8c
+#define        CB_COLOR11_ATTRIB                               0x28ea8
+
+#define        CB_COLOR1_DIM                                   0x28cb4
+#define        CB_COLOR2_DIM                                   0x28cf0
+#define        CB_COLOR3_DIM                                   0x28d2c
+#define        CB_COLOR4_DIM                                   0x28d68
+#define        CB_COLOR5_DIM                                   0x28da4
+#define        CB_COLOR6_DIM                                   0x28de0
+#define        CB_COLOR7_DIM                                   0x28e1c
+#define        CB_COLOR8_DIM                                   0x28e58
+#define        CB_COLOR9_DIM                                   0x28e74
+#define        CB_COLOR10_DIM                                  0x28e90
+#define        CB_COLOR11_DIM                                  0x28eac
+
+#define        CB_COLOR1_CMASK                                 0x28cb8
+#define        CB_COLOR2_CMASK                                 0x28cf4
+#define        CB_COLOR3_CMASK                                 0x28d30
+#define        CB_COLOR4_CMASK                                 0x28d6c
+#define        CB_COLOR5_CMASK                                 0x28da8
+#define        CB_COLOR6_CMASK                                 0x28de4
+#define        CB_COLOR7_CMASK                                 0x28e20
+
+#define        CB_COLOR1_CMASK_SLICE                           0x28cbc
+#define        CB_COLOR2_CMASK_SLICE                           0x28cf8
+#define        CB_COLOR3_CMASK_SLICE                           0x28d34
+#define        CB_COLOR4_CMASK_SLICE                           0x28d70
+#define        CB_COLOR5_CMASK_SLICE                           0x28dac
+#define        CB_COLOR6_CMASK_SLICE                           0x28de8
+#define        CB_COLOR7_CMASK_SLICE                           0x28e24
+
+#define        CB_COLOR1_FMASK                                 0x28cc0
+#define        CB_COLOR2_FMASK                                 0x28cfc
+#define        CB_COLOR3_FMASK                                 0x28d38
+#define        CB_COLOR4_FMASK                                 0x28d74
+#define        CB_COLOR5_FMASK                                 0x28db0
+#define        CB_COLOR6_FMASK                                 0x28dec
+#define        CB_COLOR7_FMASK                                 0x28e28
+
+#define        CB_COLOR1_FMASK_SLICE                           0x28cc4
+#define        CB_COLOR2_FMASK_SLICE                           0x28d00
+#define        CB_COLOR3_FMASK_SLICE                           0x28d3c
+#define        CB_COLOR4_FMASK_SLICE                           0x28d78
+#define        CB_COLOR5_FMASK_SLICE                           0x28db4
+#define        CB_COLOR6_FMASK_SLICE                           0x28df0
+#define        CB_COLOR7_FMASK_SLICE                           0x28e2c
+
+#define        CB_COLOR1_CLEAR_WORD0                           0x28cc8
+#define        CB_COLOR2_CLEAR_WORD0                           0x28d04
+#define        CB_COLOR3_CLEAR_WORD0                           0x28d40
+#define        CB_COLOR4_CLEAR_WORD0                           0x28d7c
+#define        CB_COLOR5_CLEAR_WORD0                           0x28db8
+#define        CB_COLOR6_CLEAR_WORD0                           0x28df4
+#define        CB_COLOR7_CLEAR_WORD0                           0x28e30
+
+#define        CB_COLOR1_CLEAR_WORD1                           0x28ccc
+#define        CB_COLOR2_CLEAR_WORD1                           0x28d08
+#define        CB_COLOR3_CLEAR_WORD1                           0x28d44
+#define        CB_COLOR4_CLEAR_WORD1                           0x28d80
+#define        CB_COLOR5_CLEAR_WORD1                           0x28dbc
+#define        CB_COLOR6_CLEAR_WORD1                           0x28df8
+#define        CB_COLOR7_CLEAR_WORD1                           0x28e34
+
+#define        CB_COLOR1_CLEAR_WORD2                           0x28cd0
+#define        CB_COLOR2_CLEAR_WORD2                           0x28d0c
+#define        CB_COLOR3_CLEAR_WORD2                           0x28d48
+#define        CB_COLOR4_CLEAR_WORD2                           0x28d84
+#define        CB_COLOR5_CLEAR_WORD2                           0x28dc0
+#define        CB_COLOR6_CLEAR_WORD2                           0x28dfc
+#define        CB_COLOR7_CLEAR_WORD2                           0x28e38
+
+#define        CB_COLOR1_CLEAR_WORD3                           0x28cd4
+#define        CB_COLOR2_CLEAR_WORD3                           0x28d10
+#define        CB_COLOR3_CLEAR_WORD3                           0x28d4c
+#define        CB_COLOR4_CLEAR_WORD3                           0x28d88
+#define        CB_COLOR5_CLEAR_WORD3                           0x28dc4
+#define        CB_COLOR6_CLEAR_WORD3                           0x28e00
+#define        CB_COLOR7_CLEAR_WORD3                           0x28e3c
+
+#define SQ_TEX_RESOURCE_WORD0_0                         0x30000
+#define SQ_TEX_RESOURCE_WORD1_0                         0x30004
+#       define TEX_ARRAY_MODE(x)                        ((x) << 28)
+#define SQ_TEX_RESOURCE_WORD2_0                         0x30008
+#define SQ_TEX_RESOURCE_WORD3_0                         0x3000C
+#define SQ_TEX_RESOURCE_WORD4_0                         0x30010
+#define SQ_TEX_RESOURCE_WORD5_0                         0x30014
+#define SQ_TEX_RESOURCE_WORD6_0                         0x30018
+#define SQ_TEX_RESOURCE_WORD7_0                         0x3001c
+
+
 #endif
index cc004b05d63e7ff7153b6f2f87b75f34c7062161..3970e62eaab8f75582e0838e5770a7346731bff6 100644 (file)
@@ -162,6 +162,11 @@ void r100_pm_init_profile(struct radeon_device *rdev)
        rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
        rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
        rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+       /* mid sh */
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
        /* high sh */
        rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
        rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -172,6 +177,11 @@ void r100_pm_init_profile(struct radeon_device *rdev)
        rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
        rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
        rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+       /* mid mh */
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
        /* high mh */
        rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
        rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -1618,6 +1628,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                case RADEON_TXFORMAT_RGB332:
                case RADEON_TXFORMAT_Y8:
                        track->textures[i].cpp = 1;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case RADEON_TXFORMAT_AI88:
                case RADEON_TXFORMAT_ARGB1555:
@@ -1629,12 +1640,14 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                case RADEON_TXFORMAT_LDUDV655:
                case RADEON_TXFORMAT_DUDV88:
                        track->textures[i].cpp = 2;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case RADEON_TXFORMAT_ARGB8888:
                case RADEON_TXFORMAT_RGBA8888:
                case RADEON_TXFORMAT_SHADOW32:
                case RADEON_TXFORMAT_LDUDUV8888:
                        track->textures[i].cpp = 4;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case RADEON_TXFORMAT_DXT1:
                        track->textures[i].cpp = 1;
@@ -2594,12 +2607,6 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
        int surf_index = reg * 16;
        int flags = 0;
 
-       /* r100/r200 divide by 16 */
-       if (rdev->family < CHIP_R300)
-               flags = pitch / 16;
-       else
-               flags = pitch / 8;
-
        if (rdev->family <= CHIP_RS200) {
                if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
                                 == (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
@@ -2623,6 +2630,20 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
        if (tiling_flags & RADEON_TILING_SWAP_32BIT)
                flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;
 
+       /* when we aren't tiling the pitch seems to needs to be furtherdivided down. - tested on power5 + rn50 server */
+       if (tiling_flags & (RADEON_TILING_SWAP_16BIT | RADEON_TILING_SWAP_32BIT)) {
+               if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO)))
+                       if (ASIC_IS_RN50(rdev))
+                               pitch /= 16;
+       }
+
+       /* r100/r200 divide by 16 */
+       if (rdev->family < CHIP_R300)
+               flags |= pitch / 16;
+       else
+               flags |= pitch / 8;
+
+
        DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1);
        WREG32(RADEON_SURFACE0_INFO + surf_index, flags);
        WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset);
@@ -3137,33 +3158,6 @@ static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
        DRM_ERROR("compress format            %d\n", t->compress_format);
 }
 
-static int r100_cs_track_cube(struct radeon_device *rdev,
-                             struct r100_cs_track *track, unsigned idx)
-{
-       unsigned face, w, h;
-       struct radeon_bo *cube_robj;
-       unsigned long size;
-
-       for (face = 0; face < 5; face++) {
-               cube_robj = track->textures[idx].cube_info[face].robj;
-               w = track->textures[idx].cube_info[face].width;
-               h = track->textures[idx].cube_info[face].height;
-
-               size = w * h;
-               size *= track->textures[idx].cpp;
-
-               size += track->textures[idx].cube_info[face].offset;
-
-               if (size > radeon_bo_size(cube_robj)) {
-                       DRM_ERROR("Cube texture offset greater than object size %lu %lu\n",
-                                 size, radeon_bo_size(cube_robj));
-                       r100_cs_track_texture_print(&track->textures[idx]);
-                       return -1;
-               }
-       }
-       return 0;
-}
-
 static int r100_track_compress_size(int compress_format, int w, int h)
 {
        int block_width, block_height, block_bytes;
@@ -3194,6 +3188,37 @@ static int r100_track_compress_size(int compress_format, int w, int h)
        return sz;
 }
 
+static int r100_cs_track_cube(struct radeon_device *rdev,
+                             struct r100_cs_track *track, unsigned idx)
+{
+       unsigned face, w, h;
+       struct radeon_bo *cube_robj;
+       unsigned long size;
+       unsigned compress_format = track->textures[idx].compress_format;
+
+       for (face = 0; face < 5; face++) {
+               cube_robj = track->textures[idx].cube_info[face].robj;
+               w = track->textures[idx].cube_info[face].width;
+               h = track->textures[idx].cube_info[face].height;
+
+               if (compress_format) {
+                       size = r100_track_compress_size(compress_format, w, h);
+               } else
+                       size = w * h;
+               size *= track->textures[idx].cpp;
+
+               size += track->textures[idx].cube_info[face].offset;
+
+               if (size > radeon_bo_size(cube_robj)) {
+                       DRM_ERROR("Cube texture offset greater than object size %lu %lu\n",
+                                 size, radeon_bo_size(cube_robj));
+                       r100_cs_track_texture_print(&track->textures[idx]);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
 static int r100_cs_track_texture_check(struct radeon_device *rdev,
                                       struct r100_cs_track *track)
 {
index 85617c3112127e09bd23442d6b84566ac99a29bd..0266d72e0a4cacaa8e52a79c85e6536e11b5df09 100644 (file)
@@ -415,6 +415,8 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                /* 2D, 3D, CUBE */
                switch (tmp) {
                case 0:
+               case 3:
+               case 4:
                case 5:
                case 6:
                case 7:
@@ -450,6 +452,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                case R200_TXFORMAT_RGB332:
                case R200_TXFORMAT_Y8:
                        track->textures[i].cpp = 1;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R200_TXFORMAT_AI88:
                case R200_TXFORMAT_ARGB1555:
@@ -461,6 +464,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                case R200_TXFORMAT_DVDU88:
                case R200_TXFORMAT_AVYU4444:
                        track->textures[i].cpp = 2;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R200_TXFORMAT_ARGB8888:
                case R200_TXFORMAT_RGBA8888:
@@ -468,6 +472,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                case R200_TXFORMAT_BGR111110:
                case R200_TXFORMAT_LDVDU8888:
                        track->textures[i].cpp = 4;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R200_TXFORMAT_DXT1:
                        track->textures[i].cpp = 1;
index b2f9efe2897c4362d420f61f50090fe0aedc3839..7e81db5eb8041b1c66afe1ade046724abf235805 100644 (file)
@@ -881,6 +881,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                case R300_TX_FORMAT_Y4X4:
                case R300_TX_FORMAT_Z3Y3X2:
                        track->textures[i].cpp = 1;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R300_TX_FORMAT_X16:
                case R300_TX_FORMAT_Y8X8:
@@ -892,6 +893,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                case R300_TX_FORMAT_B8G8_B8G8:
                case R300_TX_FORMAT_G8R8_G8B8:
                        track->textures[i].cpp = 2;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R300_TX_FORMAT_Y16X16:
                case R300_TX_FORMAT_Z11Y11X10:
@@ -902,14 +904,17 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                case R300_TX_FORMAT_FL_I32:
                case 0x1e:
                        track->textures[i].cpp = 4;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R300_TX_FORMAT_W16Z16Y16X16:
                case R300_TX_FORMAT_FL_R16G16B16A16:
                case R300_TX_FORMAT_FL_I32A32:
                        track->textures[i].cpp = 8;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R300_TX_FORMAT_FL_R32G32B32A32:
                        track->textures[i].cpp = 16;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R300_TX_FORMAT_DXT1:
                        track->textures[i].cpp = 1;
index 4415a5ee5871df1e353c947dd31a1dd65181cd45..e6c89142bb4d24323920636cf0e2499c5e17cf59 100644 (file)
@@ -45,9 +45,14 @@ void r420_pm_init_profile(struct radeon_device *rdev)
        rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
        /* low sh */
        rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0;
-       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
        rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
        rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+       /* mid sh */
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
        /* high sh */
        rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
        rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -58,6 +63,11 @@ void r420_pm_init_profile(struct radeon_device *rdev)
        rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
        rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
        rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+       /* mid mh */
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
        /* high mh */
        rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
        rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
index 44e96a2ae25aa2be1640d491a68570aa1257bae9..3d6645ce21518a640dd0981e38a67e223e86a49e 100644 (file)
@@ -130,9 +130,14 @@ void r600_pm_get_dynpm_state(struct radeon_device *rdev)
                                                        break;
                                                }
                                        }
-                               } else
-                                       rdev->pm.requested_power_state_index =
-                                               rdev->pm.current_power_state_index - 1;
+                               } else {
+                                       if (rdev->pm.current_power_state_index == 0)
+                                               rdev->pm.requested_power_state_index =
+                                                       rdev->pm.num_power_states - 1;
+                                       else
+                                               rdev->pm.requested_power_state_index =
+                                                       rdev->pm.current_power_state_index - 1;
+                               }
                        }
                        rdev->pm.requested_clock_mode_index = 0;
                        /* don't use the power state if crtcs are active and no display flag is set */
@@ -291,6 +296,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+               /* mid sh */
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
                /* high sh */
                rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
                rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1;
@@ -301,6 +311,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0;
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+               /* mid mh */
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
                /* high mh */
                rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
                rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 1;
@@ -317,6 +332,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+               /* mid sh */
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
                /* high sh */
                rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1;
                rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 2;
@@ -327,6 +347,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 1;
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+               /* mid mh */
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 1;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 1;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
                /* high mh */
                rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 1;
                rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2;
@@ -343,6 +368,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 2;
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+               /* mid sh */
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 2;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 2;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
                /* high sh */
                rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 2;
                rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 3;
@@ -353,6 +383,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0;
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+               /* mid mh */
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
                /* high mh */
                rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2;
                rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 3;
@@ -375,6 +410,11 @@ void r600_pm_init_profile(struct radeon_device *rdev)
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+               /* mid sh */
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
                /* high sh */
                rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
                rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -385,6 +425,11 @@ void r600_pm_init_profile(struct radeon_device *rdev)
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+               /* mid mh */
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
                /* high mh */
                rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
                rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -401,7 +446,12 @@ void r600_pm_init_profile(struct radeon_device *rdev)
                        rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1;
                        rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
                        rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
-                       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1;
+                       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+                       /* mid sh */
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1;
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1;
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
                        /* high sh */
                        rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1;
                        rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1;
@@ -411,7 +461,12 @@ void r600_pm_init_profile(struct radeon_device *rdev)
                        rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2;
                        rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 2;
                        rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
-                       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 1;
+                       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+                       /* low mh */
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2;
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 2;
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
                        /* high mh */
                        rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2;
                        rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2;
@@ -430,14 +485,30 @@ void r600_pm_init_profile(struct radeon_device *rdev)
                                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
                                        r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
                                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1;
+                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
                        } else {
                                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
                                        r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
                                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
                                        r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
                                rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1;
+                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+                       }
+                       /* mid sh */
+                       if (rdev->flags & RADEON_IS_MOBILITY) {
+                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
+                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
+                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
+                       } else {
+                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
+                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
+                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
                        }
                        /* high sh */
                        rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx =
@@ -453,14 +524,30 @@ void r600_pm_init_profile(struct radeon_device *rdev)
                                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
                                        r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
                                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 2;
+                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
                        } else {
                                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
                                        r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
                                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
                                        r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
                                rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 1;
+                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+                       }
+                       /* mid mh */
+                       if (rdev->flags & RADEON_IS_MOBILITY) {
+                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
+                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
+                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
+                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
+                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
+                       } else {
+                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
+                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
+                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
                        }
                        /* high mh */
                        rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx =
@@ -475,7 +562,18 @@ void r600_pm_init_profile(struct radeon_device *rdev)
 
 void r600_pm_misc(struct radeon_device *rdev)
 {
+       int req_ps_idx = rdev->pm.requested_power_state_index;
+       int req_cm_idx = rdev->pm.requested_clock_mode_index;
+       struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
+       struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
 
+       if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
+               if (voltage->voltage != rdev->pm.current_vddc) {
+                       radeon_atom_set_voltage(rdev, voltage->voltage);
+                       rdev->pm.current_vddc = voltage->voltage;
+                       DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
+               }
+       }
 }
 
 bool r600_gui_idle(struct radeon_device *rdev)
@@ -1004,7 +1102,7 @@ static void r600_mc_program(struct radeon_device *rdev)
        WREG32(MC_VM_FB_LOCATION, tmp);
        WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
        WREG32(HDP_NONSURFACE_INFO, (2 << 7));
-       WREG32(HDP_NONSURFACE_SIZE, rdev->mc.mc_vram_size | 0x3FF);
+       WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
        if (rdev->flags & RADEON_IS_AGP) {
                WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22);
                WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22);
@@ -1126,8 +1224,10 @@ int r600_mc_init(struct radeon_device *rdev)
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
        r600_vram_gtt_location(rdev, &rdev->mc);
 
-       if (rdev->flags & RADEON_IS_IGP)
+       if (rdev->flags & RADEON_IS_IGP) {
+               rs690_pm_info(rdev);
                rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+       }
        radeon_update_bandwidth_info(rdev);
        return 0;
 }
index 669feb689bfcdc6df0f8536493c4defc5bd0e42a..ab61aaa887bb449c486b59abccb89772b021f35a 100644 (file)
@@ -176,6 +176,8 @@ void radeon_pm_suspend(struct radeon_device *rdev);
 void radeon_pm_resume(struct radeon_device *rdev);
 void radeon_combios_get_power_modes(struct radeon_device *rdev);
 void radeon_atombios_get_power_modes(struct radeon_device *rdev);
+void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level);
+void rs690_pm_info(struct radeon_device *rdev);
 
 /*
  * Fences.
@@ -618,7 +620,8 @@ enum radeon_dynpm_state {
        DYNPM_STATE_DISABLED,
        DYNPM_STATE_MINIMUM,
        DYNPM_STATE_PAUSED,
-       DYNPM_STATE_ACTIVE
+       DYNPM_STATE_ACTIVE,
+       DYNPM_STATE_SUSPENDED,
 };
 enum radeon_dynpm_action {
        DYNPM_ACTION_NONE,
@@ -647,15 +650,18 @@ enum radeon_pm_profile_type {
        PM_PROFILE_DEFAULT,
        PM_PROFILE_AUTO,
        PM_PROFILE_LOW,
+       PM_PROFILE_MID,
        PM_PROFILE_HIGH,
 };
 
 #define PM_PROFILE_DEFAULT_IDX 0
 #define PM_PROFILE_LOW_SH_IDX  1
-#define PM_PROFILE_HIGH_SH_IDX 2
-#define PM_PROFILE_LOW_MH_IDX  3
-#define PM_PROFILE_HIGH_MH_IDX 4
-#define PM_PROFILE_MAX         5
+#define PM_PROFILE_MID_SH_IDX  2
+#define PM_PROFILE_HIGH_SH_IDX 3
+#define PM_PROFILE_LOW_MH_IDX  4
+#define PM_PROFILE_MID_MH_IDX  5
+#define PM_PROFILE_HIGH_MH_IDX 6
+#define PM_PROFILE_MAX         7
 
 struct radeon_pm_profile {
        int dpms_off_ps_idx;
@@ -744,6 +750,7 @@ struct radeon_pm {
        int                     default_power_state_index;
        u32                     current_sclk;
        u32                     current_mclk;
+       u32                     current_vddc;
        struct radeon_i2c_chan *i2c_bus;
        /* selected pm method */
        enum radeon_pm_method     pm_method;
index e57df08d4aeb9a36eb2f721ddde0f282e7365998..646f96f97c77d8538919325be4bde664a7f3df8b 100644 (file)
@@ -724,8 +724,8 @@ static struct radeon_asic evergreen_asic = {
        .irq_set = &evergreen_irq_set,
        .irq_process = &evergreen_irq_process,
        .get_vblank_counter = &evergreen_get_vblank_counter,
-       .fence_ring_emit = NULL,
-       .cs_parse = NULL,
+       .fence_ring_emit = &r600_fence_ring_emit,
+       .cs_parse = &evergreen_cs_parse,
        .copy_blit = NULL,
        .copy_dma = NULL,
        .copy = NULL,
@@ -780,6 +780,13 @@ int radeon_asic_init(struct radeon_device *rdev)
        case CHIP_R423:
        case CHIP_RV410:
                rdev->asic = &r420_asic;
+               /* handle macs */
+               if (rdev->bios == NULL) {
+                       rdev->asic->get_engine_clock = &radeon_legacy_get_engine_clock;
+                       rdev->asic->set_engine_clock = &radeon_legacy_set_engine_clock;
+                       rdev->asic->get_memory_clock = &radeon_legacy_get_memory_clock;
+                       rdev->asic->set_memory_clock = NULL;
+               }
                break;
        case CHIP_RS400:
        case CHIP_RS480:
index 5c40a3dfaca2e936679c7610468521b5c7c93b90..c0bbaa64157a466efb81990431903dc8fbe2dc33 100644 (file)
@@ -314,6 +314,7 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev,
 u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc);
 int evergreen_irq_set(struct radeon_device *rdev);
 int evergreen_irq_process(struct radeon_device *rdev);
+extern int evergreen_cs_parse(struct radeon_cs_parser *p);
 extern void evergreen_pm_misc(struct radeon_device *rdev);
 extern void evergreen_pm_prepare(struct radeon_device *rdev);
 extern void evergreen_pm_finish(struct radeon_device *rdev);
index 24ea683f7cf53ec5bd2a2958a0a86d95a5185624..99bd8a9c56b38f8431510bf3cde781345510feb1 100644 (file)
@@ -1538,7 +1538,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                        rdev->pm.power_state[state_index].pcie_lanes =
                                                power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
-                                       if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+                                       if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+                                           (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.type =
                                                        VOLTAGE_GPIO;
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1605,7 +1606,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
                                        misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
-                                       if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+                                       if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+                                           (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.type =
                                                        VOLTAGE_GPIO;
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1679,7 +1681,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
                                        misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
-                                       if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+                                       if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+                                           (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.type =
                                                        VOLTAGE_GPIO;
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1755,9 +1758,22 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                rdev->pm.power_state[state_index].misc2 = 0;
                        }
                } else {
+                       int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+                       uint8_t fw_frev, fw_crev;
+                       uint16_t fw_data_offset, vddc = 0;
+                       union firmware_info *firmware_info;
+                       ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
+
+                       if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL,
+                                                  &fw_frev, &fw_crev, &fw_data_offset)) {
+                               firmware_info =
+                                       (union firmware_info *)(mode_info->atom_context->bios +
+                                                               fw_data_offset);
+                               vddc = firmware_info->info_14.usBootUpVDDCVoltage;
+                       }
+
                        /* add the i2c bus for thermal/fan chip */
                        /* no support for internal controller yet */
-                       ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
                        if (controller->ucType > 0) {
                                if ((controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) ||
                                    (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) ||
@@ -1817,10 +1833,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                /* skip invalid modes */
                                                if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
                                                        continue;
-                                               rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
-                                                       VOLTAGE_SW;
-                                               rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
-                                                       clock_info->usVDDC;
+                                               /* voltage works differently on IGPs */
                                                mode_index++;
                                        } else if (ASIC_IS_DCE4(rdev)) {
                                                struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info =
@@ -1904,6 +1917,16 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                rdev->pm.default_power_state_index = state_index;
                                                rdev->pm.power_state[state_index].default_clock_mode =
                                                        &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
+                                               /* patch the table values with the default slck/mclk from firmware info */
+                                               for (j = 0; j < mode_index; j++) {
+                                                       rdev->pm.power_state[state_index].clock_info[j].mclk =
+                                                               rdev->clock.default_mclk;
+                                                       rdev->pm.power_state[state_index].clock_info[j].sclk =
+                                                               rdev->clock.default_sclk;
+                                                       if (vddc)
+                                                               rdev->pm.power_state[state_index].clock_info[j].voltage.voltage =
+                                                                       vddc;
+                                               }
                                        }
                                        state_index++;
                                }
@@ -1943,6 +1966,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
 
        rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
        rdev->pm.current_clock_mode_index = 0;
+       rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
 }
 
 void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
@@ -1998,6 +2022,42 @@ void radeon_atom_set_memory_clock(struct radeon_device *rdev,
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+union set_voltage {
+       struct _SET_VOLTAGE_PS_ALLOCATION alloc;
+       struct _SET_VOLTAGE_PARAMETERS v1;
+       struct _SET_VOLTAGE_PARAMETERS_V2 v2;
+};
+
+void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level)
+{
+       union set_voltage args;
+       int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
+       u8 frev, crev, volt_index = level;
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
+
+       switch (crev) {
+       case 1:
+               args.v1.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
+               args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
+               args.v1.ucVoltageIndex = volt_index;
+               break;
+       case 2:
+               args.v2.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
+               args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
+               args.v2.usVoltageLevel = cpu_to_le16(level);
+               break;
+       default:
+               DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+               return;
+       }
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+
+
 void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
 {
        struct radeon_device *rdev = dev->dev_private;
index fbba938f80481a422418fc3f095b7eef3519c212..2c92137399995f17d9df664c2ae28aa9ad8bbefa 100644 (file)
@@ -48,6 +48,10 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev)
        resource_size_t vram_base;
        resource_size_t size = 256 * 1024; /* ??? */
 
+       if (!(rdev->flags & RADEON_IS_IGP))
+               if (!radeon_card_posted(rdev))
+                       return false;
+
        rdev->bios = NULL;
        vram_base = drm_get_resource_start(rdev->ddev, 0);
        bios = ioremap(vram_base, size);
index 7b5e10d3e9c9223556f3319aba979d5cecc19c15..d1c1d8dd93ceb045257e35627f1fb429251a8d38 100644 (file)
@@ -1411,6 +1411,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT;
                } else
 #endif /* CONFIG_PPC_PMAC */
+#ifdef CONFIG_PPC64
+               if (ASIC_IS_RN50(rdev))
+                       rdev->mode_info.connector_table = CT_RN50_POWER;
+               else
+#endif
                        rdev->mode_info.connector_table = CT_GENERIC;
        }
 
@@ -1853,6 +1858,33 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                            CONNECTOR_OBJECT_ID_SVIDEO,
                                            &hpd);
                break;
+       case CT_RN50_POWER:
+               DRM_INFO("Connector Table: %d (rn50-power)\n",
+                        rdev->mode_info.connector_table);
+               /* VGA - primary dac */
+               ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+               hpd.hpd = RADEON_HPD_NONE;
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_id(dev,
+                                                               ATOM_DEVICE_CRT1_SUPPORT,
+                                                               1),
+                                         ATOM_DEVICE_CRT1_SUPPORT);
+               radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT,
+                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_VGA,
+                                           &hpd);
+               ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
+               hpd.hpd = RADEON_HPD_NONE;
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_id(dev,
+                                                               ATOM_DEVICE_CRT2_SUPPORT,
+                                                               2),
+                                         ATOM_DEVICE_CRT2_SUPPORT);
+               radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
+                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_VGA,
+                                           &hpd);
+               break;
        default:
                DRM_INFO("Connector table: %d (invalid)\n",
                         rdev->mode_info.connector_table);
@@ -1906,15 +1938,6 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev,
                        return false;
        }
 
-       /* Some RV100 cards with 2 VGA ports show up with DVI+VGA */
-       if (dev->pdev->device == 0x5159 &&
-           dev->pdev->subsystem_vendor == 0x1002 &&
-           dev->pdev->subsystem_device == 0x013a) {
-               if (*legacy_connector == CONNECTOR_DVI_I_LEGACY)
-                       *legacy_connector = CONNECTOR_CRT_LEGACY;
-
-       }
-
        /* X300 card with extra non-existent DVI port */
        if (dev->pdev->device == 0x5B60 &&
            dev->pdev->subsystem_vendor == 0x17af &&
@@ -2026,6 +2049,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                        combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
                                break;
                        default:
+                               ddc_i2c.valid = false;
                                break;
                        }
 
@@ -2339,6 +2363,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                        if (RBIOS8(tv_info + 6) == 'T') {
                                if (radeon_apply_legacy_tv_quirks(dev)) {
                                        hpd.hpd = RADEON_HPD_NONE;
+                                       ddc_i2c.valid = false;
                                        radeon_add_legacy_encoder(dev,
                                                                  radeon_get_encoder_id
                                                                  (dev,
@@ -2454,7 +2479,12 @@ default_mode:
        rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
        rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
        rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0];
-       rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
+       if ((state_index > 0) &&
+           (rdev->pm.power_state[0].clock_info[0].voltage.type == VOLTAGE_GPIO))
+               rdev->pm.power_state[state_index].clock_info[0].voltage =
+                       rdev->pm.power_state[0].clock_info[0].voltage;
+       else
+               rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
        rdev->pm.power_state[state_index].pcie_lanes = 16;
        rdev->pm.power_state[state_index].flags = 0;
        rdev->pm.default_power_state_index = state_index;
@@ -3012,6 +3042,14 @@ void radeon_combios_asic_init(struct drm_device *dev)
                combios_write_ram_size(dev);
        }
 
+       /* quirk for rs4xx HP nx6125 laptop to make it resume
+        * - it hangs on resume inside the dynclk 1 table.
+        */
+       if (rdev->family == CHIP_RS480 &&
+           rdev->pdev->subsystem_vendor == 0x103c &&
+           rdev->pdev->subsystem_device == 0x308b)
+               return;
+
        /* DYN CLK 1 */
        table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
        if (table)
index b7023fff89eb258b00d6aee84e7632954fe00384..4eb67c0e0996e539b9ad46242b25ef0070e8dfeb 100644 (file)
@@ -194,7 +194,7 @@ unpin:
 fail:
        drm_gem_object_unreference_unlocked(obj);
 
-       return 0;
+       return ret;
 }
 
 int radeon_crtc_cursor_move(struct drm_crtc *crtc,
index fdc3fdf78acb3b45dc025ae6598942d032b99bf8..5f317317aba29dc972331f32994c0acae66e9840 100644 (file)
@@ -546,8 +546,10 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
                /* don't suspend or resume card normally */
                rdev->powered_down = false;
                radeon_resume_kms(dev);
+               drm_kms_helper_poll_enable(dev);
        } else {
                printk(KERN_INFO "radeon: switched off\n");
+               drm_kms_helper_poll_disable(dev);
                radeon_suspend_kms(dev, pmm);
                /* don't suspend or resume card normally */
                rdev->powered_down = true;
@@ -711,6 +713,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 {
        struct radeon_device *rdev;
        struct drm_crtc *crtc;
+       struct drm_connector *connector;
        int r;
 
        if (dev == NULL || dev->dev_private == NULL) {
@@ -723,6 +726,12 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 
        if (rdev->powered_down)
                return 0;
+
+       /* turn off display hw */
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+       }
+
        /* unpin the front buffers */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
@@ -770,6 +779,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 
 int radeon_resume_kms(struct drm_device *dev)
 {
+       struct drm_connector *connector;
        struct radeon_device *rdev = dev->dev_private;
 
        if (rdev->powered_down)
@@ -788,6 +798,12 @@ int radeon_resume_kms(struct drm_device *dev)
        radeon_resume(rdev);
        radeon_pm_resume(rdev);
        radeon_restore_bios_scratch_regs(rdev);
+
+       /* turn on display hw */
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+       }
+
        radeon_fbdev_set_suspend(rdev, 0);
        release_console_sem();
 
index 1006549d157029bcb129129f417e1dd5195cc5ed..8154cdf796e4a752a0a33d6983852cabee7acf4a 100644 (file)
@@ -284,8 +284,7 @@ static const char *connector_names[15] = {
        "eDP",
 };
 
-static const char *hpd_names[7] = {
-       "NONE",
+static const char *hpd_names[6] = {
        "HPD1",
        "HPD2",
        "HPD3",
index 902d1731a652757b16f90b3056d3b1c8f6b7d3b8..e166fe4d7c308f55ab451a710687a679dcf8720f 100644 (file)
  * - 2.2.0 - add r6xx/r7xx const buffer support
  * - 2.3.0 - add MSPOS + 3D texture + r500 VAP regs
  * - 2.4.0 - add crtc id query
+ * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       4
+#define KMS_DRIVER_MINOR       5
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
index 1ebb100015b70b71f354ce8c4405b13455a02c8b..e0b30b264c2809997673f481bddec3a22b9d78a9 100644 (file)
@@ -1072,6 +1072,8 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        if (is_dig) {
                switch (mode) {
                case DRM_MODE_DPMS_ON:
+                       if (!ASIC_IS_DCE4(rdev))
+                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
                                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 
@@ -1079,8 +1081,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
                                if (ASIC_IS_DCE4(rdev))
                                        atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON);
                        }
-                       if (!ASIC_IS_DCE4(rdev))
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                        break;
                case DRM_MODE_DPMS_STANDBY:
                case DRM_MODE_DPMS_SUSPEND:
index e192acfbf0cdc4c098535b88e8d8216187b65bb3..dc1634bb0c11e7f0bdcda150e330fa5fa1523c2c 100644 (file)
@@ -363,6 +363,7 @@ int radeon_fbdev_init(struct radeon_device *rdev)
 {
        struct radeon_fbdev *rfbdev;
        int bpp_sel = 32;
+       int ret;
 
        /* select 8 bpp console on RN50 or 16MB cards */
        if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024))
@@ -376,9 +377,14 @@ int radeon_fbdev_init(struct radeon_device *rdev)
        rdev->mode_info.rfbdev = rfbdev;
        rfbdev->helper.funcs = &radeon_fb_helper_funcs;
 
-       drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
-                          rdev->num_crtc,
-                          RADEONFB_CONN_LIMIT);
+       ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
+                                rdev->num_crtc,
+                                RADEONFB_CONN_LIMIT);
+       if (ret) {
+               kfree(rfbdev);
+               return ret;
+       }
+
        drm_fb_helper_single_add_all_connectors(&rfbdev->helper);
        drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
        return 0;
index 04068352ccd208a0641317a81c805c2c6dd47d29..6a70c0dc7f92dbb74cdf2e24ac986b14555ef177 100644 (file)
@@ -118,7 +118,11 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                value = rdev->num_z_pipes;
                break;
        case RADEON_INFO_ACCEL_WORKING:
-               value = rdev->accel_working;
+               /* xf86-video-ati 6.13.0 relies on this being false for evergreen */
+               if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK))
+                       value = false;
+               else
+                       value = rdev->accel_working;
                break;
        case RADEON_INFO_CRTC_FROM_ID:
                for (i = 0, found = 0; i < rdev->num_crtc; i++) {
@@ -134,6 +138,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                        return -EINVAL;
                }
                break;
+       case RADEON_INFO_ACCEL_WORKING2:
+               value = rdev->accel_working;
+               break;
        default:
                DRM_DEBUG("Invalid request %d\n", info->request);
                return -EINVAL;
index 5a13b3eeef1927f2cdeeb36ca3d70de8bf69f049..bad77f40a9dad73e375ef791cfe865604aac61b6 100644 (file)
@@ -928,16 +928,14 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
        if (ASIC_IS_R300(rdev)) {
                gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
                disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
-       }
-
-       if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev))
-               disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
-       else
+       } else if (rdev->family != CHIP_R200)
                disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
-
-       if (rdev->family == CHIP_R200)
+       else if (rdev->family == CHIP_R200)
                fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
 
+       if (rdev->family >= CHIP_R200)
+               disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
+
        if (is_tv) {
                uint32_t dac_cntl;
 
@@ -1002,15 +1000,13 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
        if (ASIC_IS_R300(rdev)) {
                WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
                WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
-       }
+       } else if (rdev->family != CHIP_R200)
+               WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+       else if (rdev->family == CHIP_R200)
+               WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
 
        if (rdev->family >= CHIP_R200)
                WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl);
-       else
-               WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
-
-       if (rdev->family == CHIP_R200)
-               WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
 
        if (is_tv)
                radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode);
@@ -1168,6 +1164,17 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
        bool color = true;
+       struct drm_crtc *crtc;
+
+       /* find out if crtc2 is in use or if this encoder is using it */
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+               if ((radeon_crtc->crtc_id == 1) && crtc->enabled) {
+                       if (encoder->crtc != crtc) {
+                               return connector_status_disconnected;
+                       }
+               }
+       }
 
        if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
            connector->connector_type == DRM_MODE_CONNECTOR_Composite ||
index 67358baf28b2930c4dc999a2b6e63a7e5c9e8d98..95696aa57ac8c43048071ba93fd4254ec113ac92 100644 (file)
@@ -206,6 +206,7 @@ enum radeon_connector_table {
        CT_MINI_INTERNAL,
        CT_IMAC_G5_ISIGHT,
        CT_EMAC,
+       CT_RN50_POWER,
 };
 
 enum radeon_dvo_chip {
index a8d162c6f82966e83b482e41187af4a37e2b4957..115d26b762cc2b3db9301c86e66d97505f6fd291 100644 (file)
 #define RADEON_WAIT_VBLANK_TIMEOUT 200
 #define RADEON_WAIT_IDLE_TIMEOUT 200
 
+static const char *radeon_pm_state_type_name[5] = {
+       "Default",
+       "Powersave",
+       "Battery",
+       "Balanced",
+       "Performance",
+};
+
 static void radeon_dynpm_idle_work_handler(struct work_struct *work);
 static int radeon_debugfs_pm_init(struct radeon_device *rdev);
 static bool radeon_pm_in_vbl(struct radeon_device *rdev);
@@ -84,9 +92,9 @@ static void radeon_pm_update_profile(struct radeon_device *rdev)
                                rdev->pm.profile_index = PM_PROFILE_HIGH_SH_IDX;
                } else {
                        if (rdev->pm.active_crtc_count > 1)
-                               rdev->pm.profile_index = PM_PROFILE_LOW_MH_IDX;
+                               rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX;
                        else
-                               rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX;
+                               rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX;
                }
                break;
        case PM_PROFILE_LOW:
@@ -95,6 +103,12 @@ static void radeon_pm_update_profile(struct radeon_device *rdev)
                else
                        rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX;
                break;
+       case PM_PROFILE_MID:
+               if (rdev->pm.active_crtc_count > 1)
+                       rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX;
+               else
+                       rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX;
+               break;
        case PM_PROFILE_HIGH:
                if (rdev->pm.active_crtc_count > 1)
                        rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX;
@@ -127,15 +141,6 @@ static void radeon_unmap_vram_bos(struct radeon_device *rdev)
                if (bo->tbo.mem.mem_type == TTM_PL_VRAM)
                        ttm_bo_unmap_virtual(&bo->tbo);
        }
-
-       if (rdev->gart.table.vram.robj)
-               ttm_bo_unmap_virtual(&rdev->gart.table.vram.robj->tbo);
-
-       if (rdev->stollen_vga_memory)
-               ttm_bo_unmap_virtual(&rdev->stollen_vga_memory->tbo);
-
-       if (rdev->r600_blit.shader_obj)
-               ttm_bo_unmap_virtual(&rdev->r600_blit.shader_obj->tbo);
 }
 
 static void radeon_sync_with_vblank(struct radeon_device *rdev)
@@ -151,6 +156,7 @@ static void radeon_sync_with_vblank(struct radeon_device *rdev)
 static void radeon_set_power_state(struct radeon_device *rdev)
 {
        u32 sclk, mclk;
+       bool misc_after = false;
 
        if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
            (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
@@ -167,55 +173,47 @@ static void radeon_set_power_state(struct radeon_device *rdev)
                if (mclk > rdev->clock.default_mclk)
                        mclk = rdev->clock.default_mclk;
 
-               /* voltage, pcie lanes, etc.*/
-               radeon_pm_misc(rdev);
+               /* upvolt before raising clocks, downvolt after lowering clocks */
+               if (sclk < rdev->pm.current_sclk)
+                       misc_after = true;
 
-               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
-                       radeon_sync_with_vblank(rdev);
+               radeon_sync_with_vblank(rdev);
 
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                        if (!radeon_pm_in_vbl(rdev))
                                return;
+               }
 
-                       radeon_pm_prepare(rdev);
-                       /* set engine clock */
-                       if (sclk != rdev->pm.current_sclk) {
-                               radeon_pm_debug_check_in_vbl(rdev, false);
-                               radeon_set_engine_clock(rdev, sclk);
-                               radeon_pm_debug_check_in_vbl(rdev, true);
-                               rdev->pm.current_sclk = sclk;
-                               DRM_DEBUG("Setting: e: %d\n", sclk);
-                       }
+               radeon_pm_prepare(rdev);
 
-                       /* set memory clock */
-                       if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
-                               radeon_pm_debug_check_in_vbl(rdev, false);
-                               radeon_set_memory_clock(rdev, mclk);
-                               radeon_pm_debug_check_in_vbl(rdev, true);
-                               rdev->pm.current_mclk = mclk;
-                               DRM_DEBUG("Setting: m: %d\n", mclk);
-                       }
-                       radeon_pm_finish(rdev);
-               } else {
-                       /* set engine clock */
-                       if (sclk != rdev->pm.current_sclk) {
-                               radeon_sync_with_vblank(rdev);
-                               radeon_pm_prepare(rdev);
-                               radeon_set_engine_clock(rdev, sclk);
-                               radeon_pm_finish(rdev);
-                               rdev->pm.current_sclk = sclk;
-                               DRM_DEBUG("Setting: e: %d\n", sclk);
-                       }
-                       /* set memory clock */
-                       if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
-                               radeon_sync_with_vblank(rdev);
-                               radeon_pm_prepare(rdev);
-                               radeon_set_memory_clock(rdev, mclk);
-                               radeon_pm_finish(rdev);
-                               rdev->pm.current_mclk = mclk;
-                               DRM_DEBUG("Setting: m: %d\n", mclk);
-                       }
+               if (!misc_after)
+                       /* voltage, pcie lanes, etc.*/
+                       radeon_pm_misc(rdev);
+
+               /* set engine clock */
+               if (sclk != rdev->pm.current_sclk) {
+                       radeon_pm_debug_check_in_vbl(rdev, false);
+                       radeon_set_engine_clock(rdev, sclk);
+                       radeon_pm_debug_check_in_vbl(rdev, true);
+                       rdev->pm.current_sclk = sclk;
+                       DRM_DEBUG("Setting: e: %d\n", sclk);
                }
 
+               /* set memory clock */
+               if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
+                       radeon_pm_debug_check_in_vbl(rdev, false);
+                       radeon_set_memory_clock(rdev, mclk);
+                       radeon_pm_debug_check_in_vbl(rdev, true);
+                       rdev->pm.current_mclk = mclk;
+                       DRM_DEBUG("Setting: m: %d\n", mclk);
+               }
+
+               if (misc_after)
+                       /* voltage, pcie lanes, etc.*/
+                       radeon_pm_misc(rdev);
+
+               radeon_pm_finish(rdev);
+
                rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
                rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
        } else
@@ -288,6 +286,42 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
        mutex_unlock(&rdev->ddev->struct_mutex);
 }
 
+static void radeon_pm_print_states(struct radeon_device *rdev)
+{
+       int i, j;
+       struct radeon_power_state *power_state;
+       struct radeon_pm_clock_info *clock_info;
+
+       DRM_DEBUG("%d Power State(s)\n", rdev->pm.num_power_states);
+       for (i = 0; i < rdev->pm.num_power_states; i++) {
+               power_state = &rdev->pm.power_state[i];
+               DRM_DEBUG("State %d: %s\n", i,
+                       radeon_pm_state_type_name[power_state->type]);
+               if (i == rdev->pm.default_power_state_index)
+                       DRM_DEBUG("\tDefault");
+               if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP))
+                       DRM_DEBUG("\t%d PCIE Lanes\n", power_state->pcie_lanes);
+               if (power_state->flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
+                       DRM_DEBUG("\tSingle display only\n");
+               DRM_DEBUG("\t%d Clock Mode(s)\n", power_state->num_clock_modes);
+               for (j = 0; j < power_state->num_clock_modes; j++) {
+                       clock_info = &(power_state->clock_info[j]);
+                       if (rdev->flags & RADEON_IS_IGP)
+                               DRM_DEBUG("\t\t%d e: %d%s\n",
+                                       j,
+                                       clock_info->sclk * 10,
+                                       clock_info->flags & RADEON_PM_MODE_NO_DISPLAY ? "\tNo display only" : "");
+                       else
+                               DRM_DEBUG("\t\t%d e: %d\tm: %d\tv: %d%s\n",
+                                       j,
+                                       clock_info->sclk * 10,
+                                       clock_info->mclk * 10,
+                                       clock_info->voltage.voltage,
+                                       clock_info->flags & RADEON_PM_MODE_NO_DISPLAY ? "\tNo display only" : "");
+               }
+       }
+}
+
 static ssize_t radeon_get_pm_profile(struct device *dev,
                                     struct device_attribute *attr,
                                     char *buf)
@@ -318,6 +352,8 @@ static ssize_t radeon_set_pm_profile(struct device *dev,
                        rdev->pm.profile = PM_PROFILE_AUTO;
                else if (strncmp("low", buf, strlen("low")) == 0)
                        rdev->pm.profile = PM_PROFILE_LOW;
+               else if (strncmp("mid", buf, strlen("mid")) == 0)
+                       rdev->pm.profile = PM_PROFILE_MID;
                else if (strncmp("high", buf, strlen("high")) == 0)
                        rdev->pm.profile = PM_PROFILE_HIGH;
                else {
@@ -361,13 +397,20 @@ static ssize_t radeon_set_pm_method(struct device *dev,
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                mutex_unlock(&rdev->pm.mutex);
        } else if (strncmp("profile", buf, strlen("profile")) == 0) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
-               rdev->pm.pm_method = PM_METHOD_PROFILE;
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
+               }
                /* disable dynpm */
                rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               rdev->pm.pm_method = PM_METHOD_PROFILE;
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
        } else {
                DRM_ERROR("invalid power method!\n");
                goto fail;
@@ -382,17 +425,36 @@ static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon
 
 void radeon_pm_suspend(struct radeon_device *rdev)
 {
+       bool flush_wq = false;
+
        mutex_lock(&rdev->pm.mutex);
-       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
-       rdev->pm.current_power_state_index = -1;
-       rdev->pm.current_clock_mode_index = -1;
-       rdev->pm.current_sclk = 0;
-       rdev->pm.current_mclk = 0;
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+                       rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+               flush_wq = true;
+       }
        mutex_unlock(&rdev->pm.mutex);
+       if (flush_wq)
+               flush_workqueue(rdev->wq);
 }
 
 void radeon_pm_resume(struct radeon_device *rdev)
 {
+       /* asic init will reset the default power state */
+       mutex_lock(&rdev->pm.mutex);
+       rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
+       rdev->pm.current_clock_mode_index = 0;
+       rdev->pm.current_sclk = rdev->clock.default_sclk;
+       rdev->pm.current_mclk = rdev->clock.default_mclk;
+       rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM
+           && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+               rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+       }
+       mutex_unlock(&rdev->pm.mutex);
        radeon_pm_compute_clocks(rdev);
 }
 
@@ -401,32 +463,24 @@ int radeon_pm_init(struct radeon_device *rdev)
        int ret;
        /* default to profile method */
        rdev->pm.pm_method = PM_METHOD_PROFILE;
+       rdev->pm.profile = PM_PROFILE_DEFAULT;
        rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
        rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
        rdev->pm.dynpm_can_upclock = true;
        rdev->pm.dynpm_can_downclock = true;
-       rdev->pm.current_sclk = 0;
-       rdev->pm.current_mclk = 0;
+       rdev->pm.current_sclk = rdev->clock.default_sclk;
+       rdev->pm.current_mclk = rdev->clock.default_mclk;
 
        if (rdev->bios) {
                if (rdev->is_atom_bios)
                        radeon_atombios_get_power_modes(rdev);
                else
                        radeon_combios_get_power_modes(rdev);
+               radeon_pm_print_states(rdev);
                radeon_pm_init_profile(rdev);
-               rdev->pm.current_power_state_index = -1;
-               rdev->pm.current_clock_mode_index = -1;
        }
 
        if (rdev->pm.num_power_states > 1) {
-               if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
-                       mutex_lock(&rdev->pm.mutex);
-                       rdev->pm.profile = PM_PROFILE_DEFAULT;
-                       radeon_pm_update_profile(rdev);
-                       radeon_pm_set_clocks(rdev);
-                       mutex_unlock(&rdev->pm.mutex);
-               }
-
                /* where's the best place to put these? */
                ret = device_create_file(rdev->dev, &dev_attr_power_profile);
                if (ret)
@@ -454,6 +508,8 @@ int radeon_pm_init(struct radeon_device *rdev)
 void radeon_pm_fini(struct radeon_device *rdev)
 {
        if (rdev->pm.num_power_states > 1) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
                if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                        rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -461,13 +517,16 @@ void radeon_pm_fini(struct radeon_device *rdev)
                        radeon_pm_set_clocks(rdev);
                } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                        /* cancel work */
-                       cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
                        /* reset default clocks */
                        rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                        rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                        radeon_pm_set_clocks(rdev);
                }
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
 
                device_remove_file(rdev->dev, &dev_attr_power_profile);
                device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -688,12 +747,12 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work)
                        radeon_pm_get_dynpm_state(rdev);
                        radeon_pm_set_clocks(rdev);
                }
+
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
        }
        mutex_unlock(&rdev->pm.mutex);
        ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-       queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 }
 
 /*
@@ -712,6 +771,8 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data)
        seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk);
        if (rdev->asic->get_memory_clock)
                seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
+       if (rdev->pm.current_vddc)
+               seq_printf(m, "voltage: %u mV\n", rdev->pm.current_vddc);
        if (rdev->asic->get_pcie_lanes)
                seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev));
 
diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen
new file mode 100644 (file)
index 0000000..f78fd59
--- /dev/null
@@ -0,0 +1,611 @@
+evergreen 0x9400
+0x00008040 WAIT_UNTIL
+0x00008044 WAIT_UNTIL_POLL_CNTL
+0x00008048 WAIT_UNTIL_POLL_MASK
+0x0000804c WAIT_UNTIL_POLL_REFDATA
+0x000088B0 VGT_VTX_VECT_EJECT_REG
+0x000088C4 VGT_CACHE_INVALIDATION
+0x000088D4 VGT_GS_VERTEX_REUSE
+0x00008958 VGT_PRIMITIVE_TYPE
+0x0000895C VGT_INDEX_TYPE
+0x00008970 VGT_NUM_INDICES
+0x00008974 VGT_NUM_INSTANCES
+0x00008990 VGT_COMPUTE_DIM_X
+0x00008994 VGT_COMPUTE_DIM_Y
+0x00008998 VGT_COMPUTE_DIM_Z
+0x0000899C VGT_COMPUTE_START_X
+0x000089A0 VGT_COMPUTE_START_Y
+0x000089A4 VGT_COMPUTE_START_Z
+0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
+0x00008A14 PA_CL_ENHANCE
+0x00008A60 PA_SC_LINE_STIPPLE_VALUE
+0x00008B10 PA_SC_LINE_STIPPLE_STATE
+0x00008BF0 PA_SC_ENHANCE
+0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
+0x00008C00 SQ_CONFIG
+0x00008C04 SQ_GPR_RESOURCE_MGMT_1
+0x00008C08 SQ_GPR_RESOURCE_MGMT_2
+0x00008C0C SQ_GPR_RESOURCE_MGMT_3
+0x00008C10 SQ_GLOBAL_GPR_RESOURCE_MGMT_1
+0x00008C14 SQ_GLOBAL_GPR_RESOURCE_MGMT_2
+0x00008C18 SQ_THREAD_RESOURCE_MGMT
+0x00008C1C SQ_THREAD_RESOURCE_MGMT_2
+0x00008C20 SQ_STACK_RESOURCE_MGMT_1
+0x00008C24 SQ_STACK_RESOURCE_MGMT_2
+0x00008C28 SQ_STACK_RESOURCE_MGMT_3
+0x00008DF8 SQ_CONST_MEM_BASE
+0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
+0x00009100 SPI_CONFIG_CNTL
+0x0000913C SPI_CONFIG_CNTL_1
+0x00009700 VC_CNTL
+0x00009714 VC_ENHANCE
+0x00009830 DB_DEBUG
+0x00009834 DB_DEBUG2
+0x00009838 DB_DEBUG3
+0x0000983C DB_DEBUG4
+0x00009854 DB_WATERMARKS
+0x0000A400 TD_PS_BORDER_COLOR_INDEX
+0x0000A404 TD_PS_BORDER_COLOR_RED
+0x0000A408 TD_PS_BORDER_COLOR_GREEN
+0x0000A40C TD_PS_BORDER_COLOR_BLUE
+0x0000A410 TD_PS_BORDER_COLOR_ALPHA
+0x0000A414 TD_VS_BORDER_COLOR_INDEX
+0x0000A418 TD_VS_BORDER_COLOR_RED
+0x0000A41C TD_VS_BORDER_COLOR_GREEN
+0x0000A420 TD_VS_BORDER_COLOR_BLUE
+0x0000A424 TD_VS_BORDER_COLOR_ALPHA
+0x0000A428 TD_GS_BORDER_COLOR_INDEX
+0x0000A42C TD_GS_BORDER_COLOR_RED
+0x0000A430 TD_GS_BORDER_COLOR_GREEN
+0x0000A434 TD_GS_BORDER_COLOR_BLUE
+0x0000A438 TD_GS_BORDER_COLOR_ALPHA
+0x0000A43C TD_HS_BORDER_COLOR_INDEX
+0x0000A440 TD_HS_BORDER_COLOR_RED
+0x0000A444 TD_HS_BORDER_COLOR_GREEN
+0x0000A448 TD_HS_BORDER_COLOR_BLUE
+0x0000A44C TD_HS_BORDER_COLOR_ALPHA
+0x0000A450 TD_LS_BORDER_COLOR_INDEX
+0x0000A454 TD_LS_BORDER_COLOR_RED
+0x0000A458 TD_LS_BORDER_COLOR_GREEN
+0x0000A45C TD_LS_BORDER_COLOR_BLUE
+0x0000A460 TD_LS_BORDER_COLOR_ALPHA
+0x0000A464 TD_CS_BORDER_COLOR_INDEX
+0x0000A468 TD_CS_BORDER_COLOR_RED
+0x0000A46C TD_CS_BORDER_COLOR_GREEN
+0x0000A470 TD_CS_BORDER_COLOR_BLUE
+0x0000A474 TD_CS_BORDER_COLOR_ALPHA
+0x00028000 DB_RENDER_CONTROL
+0x00028004 DB_COUNT_CONTROL
+0x0002800C DB_RENDER_OVERRIDE
+0x00028010 DB_RENDER_OVERRIDE2
+0x00028028 DB_STENCIL_CLEAR
+0x0002802C DB_DEPTH_CLEAR
+0x00028030 PA_SC_SCREEN_SCISSOR_TL
+0x00028034 PA_SC_SCREEN_SCISSOR_BR
+0x0002805C DB_DEPTH_SLICE
+0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0
+0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1
+0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2
+0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3
+0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4
+0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5
+0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6
+0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7
+0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8
+0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9
+0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10
+0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11
+0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12
+0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13
+0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14
+0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15
+0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0
+0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1
+0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2
+0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3
+0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4
+0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5
+0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6
+0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7
+0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8
+0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9
+0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10
+0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11
+0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12
+0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13
+0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14
+0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15
+0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0
+0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1
+0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2
+0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3
+0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4
+0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5
+0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6
+0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7
+0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8
+0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9
+0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10
+0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11
+0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12
+0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13
+0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14
+0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15
+0x00028200 PA_SC_WINDOW_OFFSET
+0x00028204 PA_SC_WINDOW_SCISSOR_TL
+0x00028208 PA_SC_WINDOW_SCISSOR_BR
+0x0002820C PA_SC_CLIPRECT_RULE
+0x00028210 PA_SC_CLIPRECT_0_TL
+0x00028214 PA_SC_CLIPRECT_0_BR
+0x00028218 PA_SC_CLIPRECT_1_TL
+0x0002821C PA_SC_CLIPRECT_1_BR
+0x00028220 PA_SC_CLIPRECT_2_TL
+0x00028224 PA_SC_CLIPRECT_2_BR
+0x00028228 PA_SC_CLIPRECT_3_TL
+0x0002822C PA_SC_CLIPRECT_3_BR
+0x00028230 PA_SC_EDGERULE
+0x00028234 PA_SU_HARDWARE_SCREEN_OFFSET
+0x00028240 PA_SC_GENERIC_SCISSOR_TL
+0x00028244 PA_SC_GENERIC_SCISSOR_BR
+0x00028250 PA_SC_VPORT_SCISSOR_0_TL
+0x00028254 PA_SC_VPORT_SCISSOR_0_BR
+0x00028258 PA_SC_VPORT_SCISSOR_1_TL
+0x0002825C PA_SC_VPORT_SCISSOR_1_BR
+0x00028260 PA_SC_VPORT_SCISSOR_2_TL
+0x00028264 PA_SC_VPORT_SCISSOR_2_BR
+0x00028268 PA_SC_VPORT_SCISSOR_3_TL
+0x0002826C PA_SC_VPORT_SCISSOR_3_BR
+0x00028270 PA_SC_VPORT_SCISSOR_4_TL
+0x00028274 PA_SC_VPORT_SCISSOR_4_BR
+0x00028278 PA_SC_VPORT_SCISSOR_5_TL
+0x0002827C PA_SC_VPORT_SCISSOR_5_BR
+0x00028280 PA_SC_VPORT_SCISSOR_6_TL
+0x00028284 PA_SC_VPORT_SCISSOR_6_BR
+0x00028288 PA_SC_VPORT_SCISSOR_7_TL
+0x0002828C PA_SC_VPORT_SCISSOR_7_BR
+0x00028290 PA_SC_VPORT_SCISSOR_8_TL
+0x00028294 PA_SC_VPORT_SCISSOR_8_BR
+0x00028298 PA_SC_VPORT_SCISSOR_9_TL
+0x0002829C PA_SC_VPORT_SCISSOR_9_BR
+0x000282A0 PA_SC_VPORT_SCISSOR_10_TL
+0x000282A4 PA_SC_VPORT_SCISSOR_10_BR
+0x000282A8 PA_SC_VPORT_SCISSOR_11_TL
+0x000282AC PA_SC_VPORT_SCISSOR_11_BR
+0x000282B0 PA_SC_VPORT_SCISSOR_12_TL
+0x000282B4 PA_SC_VPORT_SCISSOR_12_BR
+0x000282B8 PA_SC_VPORT_SCISSOR_13_TL
+0x000282BC PA_SC_VPORT_SCISSOR_13_BR
+0x000282C0 PA_SC_VPORT_SCISSOR_14_TL
+0x000282C4 PA_SC_VPORT_SCISSOR_14_BR
+0x000282C8 PA_SC_VPORT_SCISSOR_15_TL
+0x000282CC PA_SC_VPORT_SCISSOR_15_BR
+0x000282D0 PA_SC_VPORT_ZMIN_0
+0x000282D4 PA_SC_VPORT_ZMAX_0
+0x000282D8 PA_SC_VPORT_ZMIN_1
+0x000282DC PA_SC_VPORT_ZMAX_1
+0x000282E0 PA_SC_VPORT_ZMIN_2
+0x000282E4 PA_SC_VPORT_ZMAX_2
+0x000282E8 PA_SC_VPORT_ZMIN_3
+0x000282EC PA_SC_VPORT_ZMAX_3
+0x000282F0 PA_SC_VPORT_ZMIN_4
+0x000282F4 PA_SC_VPORT_ZMAX_4
+0x000282F8 PA_SC_VPORT_ZMIN_5
+0x000282FC PA_SC_VPORT_ZMAX_5
+0x00028300 PA_SC_VPORT_ZMIN_6
+0x00028304 PA_SC_VPORT_ZMAX_6
+0x00028308 PA_SC_VPORT_ZMIN_7
+0x0002830C PA_SC_VPORT_ZMAX_7
+0x00028310 PA_SC_VPORT_ZMIN_8
+0x00028314 PA_SC_VPORT_ZMAX_8
+0x00028318 PA_SC_VPORT_ZMIN_9
+0x0002831C PA_SC_VPORT_ZMAX_9
+0x00028320 PA_SC_VPORT_ZMIN_10
+0x00028324 PA_SC_VPORT_ZMAX_10
+0x00028328 PA_SC_VPORT_ZMIN_11
+0x0002832C PA_SC_VPORT_ZMAX_11
+0x00028330 PA_SC_VPORT_ZMIN_12
+0x00028334 PA_SC_VPORT_ZMAX_12
+0x00028338 PA_SC_VPORT_ZMIN_13
+0x0002833C PA_SC_VPORT_ZMAX_13
+0x00028340 PA_SC_VPORT_ZMIN_14
+0x00028344 PA_SC_VPORT_ZMAX_14
+0x00028348 PA_SC_VPORT_ZMIN_15
+0x0002834C PA_SC_VPORT_ZMAX_15
+0x00028350 SX_MISC
+0x00028380 SQ_VTX_SEMANTIC_0
+0x00028384 SQ_VTX_SEMANTIC_1
+0x00028388 SQ_VTX_SEMANTIC_2
+0x0002838C SQ_VTX_SEMANTIC_3
+0x00028390 SQ_VTX_SEMANTIC_4
+0x00028394 SQ_VTX_SEMANTIC_5
+0x00028398 SQ_VTX_SEMANTIC_6
+0x0002839C SQ_VTX_SEMANTIC_7
+0x000283A0 SQ_VTX_SEMANTIC_8
+0x000283A4 SQ_VTX_SEMANTIC_9
+0x000283A8 SQ_VTX_SEMANTIC_10
+0x000283AC SQ_VTX_SEMANTIC_11
+0x000283B0 SQ_VTX_SEMANTIC_12
+0x000283B4 SQ_VTX_SEMANTIC_13
+0x000283B8 SQ_VTX_SEMANTIC_14
+0x000283BC SQ_VTX_SEMANTIC_15
+0x000283C0 SQ_VTX_SEMANTIC_16
+0x000283C4 SQ_VTX_SEMANTIC_17
+0x000283C8 SQ_VTX_SEMANTIC_18
+0x000283CC SQ_VTX_SEMANTIC_19
+0x000283D0 SQ_VTX_SEMANTIC_20
+0x000283D4 SQ_VTX_SEMANTIC_21
+0x000283D8 SQ_VTX_SEMANTIC_22
+0x000283DC SQ_VTX_SEMANTIC_23
+0x000283E0 SQ_VTX_SEMANTIC_24
+0x000283E4 SQ_VTX_SEMANTIC_25
+0x000283E8 SQ_VTX_SEMANTIC_26
+0x000283EC SQ_VTX_SEMANTIC_27
+0x000283F0 SQ_VTX_SEMANTIC_28
+0x000283F4 SQ_VTX_SEMANTIC_29
+0x000283F8 SQ_VTX_SEMANTIC_30
+0x000283FC SQ_VTX_SEMANTIC_31
+0x00028400 VGT_MAX_VTX_INDX
+0x00028404 VGT_MIN_VTX_INDX
+0x00028408 VGT_INDX_OFFSET
+0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX
+0x00028410 SX_ALPHA_TEST_CONTROL
+0x00028414 CB_BLEND_RED
+0x00028418 CB_BLEND_GREEN
+0x0002841C CB_BLEND_BLUE
+0x00028420 CB_BLEND_ALPHA
+0x00028430 DB_STENCILREFMASK
+0x00028434 DB_STENCILREFMASK_BF
+0x00028438 SX_ALPHA_REF
+0x0002843C PA_CL_VPORT_XSCALE_0
+0x00028440 PA_CL_VPORT_XOFFSET_0
+0x00028444 PA_CL_VPORT_YSCALE_0
+0x00028448 PA_CL_VPORT_YOFFSET_0
+0x0002844C PA_CL_VPORT_ZSCALE_0
+0x00028450 PA_CL_VPORT_ZOFFSET_0
+0x00028454 PA_CL_VPORT_XSCALE_1
+0x00028458 PA_CL_VPORT_XOFFSET_1
+0x0002845C PA_CL_VPORT_YSCALE_1
+0x00028460 PA_CL_VPORT_YOFFSET_1
+0x00028464 PA_CL_VPORT_ZSCALE_1
+0x00028468 PA_CL_VPORT_ZOFFSET_1
+0x0002846C PA_CL_VPORT_XSCALE_2
+0x00028470 PA_CL_VPORT_XOFFSET_2
+0x00028474 PA_CL_VPORT_YSCALE_2
+0x00028478 PA_CL_VPORT_YOFFSET_2
+0x0002847C PA_CL_VPORT_ZSCALE_2
+0x00028480 PA_CL_VPORT_ZOFFSET_2
+0x00028484 PA_CL_VPORT_XSCALE_3
+0x00028488 PA_CL_VPORT_XOFFSET_3
+0x0002848C PA_CL_VPORT_YSCALE_3
+0x00028490 PA_CL_VPORT_YOFFSET_3
+0x00028494 PA_CL_VPORT_ZSCALE_3
+0x00028498 PA_CL_VPORT_ZOFFSET_3
+0x0002849C PA_CL_VPORT_XSCALE_4
+0x000284A0 PA_CL_VPORT_XOFFSET_4
+0x000284A4 PA_CL_VPORT_YSCALE_4
+0x000284A8 PA_CL_VPORT_YOFFSET_4
+0x000284AC PA_CL_VPORT_ZSCALE_4
+0x000284B0 PA_CL_VPORT_ZOFFSET_4
+0x000284B4 PA_CL_VPORT_XSCALE_5
+0x000284B8 PA_CL_VPORT_XOFFSET_5
+0x000284BC PA_CL_VPORT_YSCALE_5
+0x000284C0 PA_CL_VPORT_YOFFSET_5
+0x000284C4 PA_CL_VPORT_ZSCALE_5
+0x000284C8 PA_CL_VPORT_ZOFFSET_5
+0x000284CC PA_CL_VPORT_XSCALE_6
+0x000284D0 PA_CL_VPORT_XOFFSET_6
+0x000284D4 PA_CL_VPORT_YSCALE_6
+0x000284D8 PA_CL_VPORT_YOFFSET_6
+0x000284DC PA_CL_VPORT_ZSCALE_6
+0x000284E0 PA_CL_VPORT_ZOFFSET_6
+0x000284E4 PA_CL_VPORT_XSCALE_7
+0x000284E8 PA_CL_VPORT_XOFFSET_7
+0x000284EC PA_CL_VPORT_YSCALE_7
+0x000284F0 PA_CL_VPORT_YOFFSET_7
+0x000284F4 PA_CL_VPORT_ZSCALE_7
+0x000284F8 PA_CL_VPORT_ZOFFSET_7
+0x000284FC PA_CL_VPORT_XSCALE_8
+0x00028500 PA_CL_VPORT_XOFFSET_8
+0x00028504 PA_CL_VPORT_YSCALE_8
+0x00028508 PA_CL_VPORT_YOFFSET_8
+0x0002850C PA_CL_VPORT_ZSCALE_8
+0x00028510 PA_CL_VPORT_ZOFFSET_8
+0x00028514 PA_CL_VPORT_XSCALE_9
+0x00028518 PA_CL_VPORT_XOFFSET_9
+0x0002851C PA_CL_VPORT_YSCALE_9
+0x00028520 PA_CL_VPORT_YOFFSET_9
+0x00028524 PA_CL_VPORT_ZSCALE_9
+0x00028528 PA_CL_VPORT_ZOFFSET_9
+0x0002852C PA_CL_VPORT_XSCALE_10
+0x00028530 PA_CL_VPORT_XOFFSET_10
+0x00028534 PA_CL_VPORT_YSCALE_10
+0x00028538 PA_CL_VPORT_YOFFSET_10
+0x0002853C PA_CL_VPORT_ZSCALE_10
+0x00028540 PA_CL_VPORT_ZOFFSET_10
+0x00028544 PA_CL_VPORT_XSCALE_11
+0x00028548 PA_CL_VPORT_XOFFSET_11
+0x0002854C PA_CL_VPORT_YSCALE_11
+0x00028550 PA_CL_VPORT_YOFFSET_11
+0x00028554 PA_CL_VPORT_ZSCALE_11
+0x00028558 PA_CL_VPORT_ZOFFSET_11
+0x0002855C PA_CL_VPORT_XSCALE_12
+0x00028560 PA_CL_VPORT_XOFFSET_12
+0x00028564 PA_CL_VPORT_YSCALE_12
+0x00028568 PA_CL_VPORT_YOFFSET_12
+0x0002856C PA_CL_VPORT_ZSCALE_12
+0x00028570 PA_CL_VPORT_ZOFFSET_12
+0x00028574 PA_CL_VPORT_XSCALE_13
+0x00028578 PA_CL_VPORT_XOFFSET_13
+0x0002857C PA_CL_VPORT_YSCALE_13
+0x00028580 PA_CL_VPORT_YOFFSET_13
+0x00028584 PA_CL_VPORT_ZSCALE_13
+0x00028588 PA_CL_VPORT_ZOFFSET_13
+0x0002858C PA_CL_VPORT_XSCALE_14
+0x00028590 PA_CL_VPORT_XOFFSET_14
+0x00028594 PA_CL_VPORT_YSCALE_14
+0x00028598 PA_CL_VPORT_YOFFSET_14
+0x0002859C PA_CL_VPORT_ZSCALE_14
+0x000285A0 PA_CL_VPORT_ZOFFSET_14
+0x000285A4 PA_CL_VPORT_XSCALE_15
+0x000285A8 PA_CL_VPORT_XOFFSET_15
+0x000285AC PA_CL_VPORT_YSCALE_15
+0x000285B0 PA_CL_VPORT_YOFFSET_15
+0x000285B4 PA_CL_VPORT_ZSCALE_15
+0x000285B8 PA_CL_VPORT_ZOFFSET_15
+0x000285BC PA_CL_UCP_0_X
+0x000285C0 PA_CL_UCP_0_Y
+0x000285C4 PA_CL_UCP_0_Z
+0x000285C8 PA_CL_UCP_0_W
+0x000285CC PA_CL_UCP_1_X
+0x000285D0 PA_CL_UCP_1_Y
+0x000285D4 PA_CL_UCP_1_Z
+0x000285D8 PA_CL_UCP_1_W
+0x000285DC PA_CL_UCP_2_X
+0x000285E0 PA_CL_UCP_2_Y
+0x000285E4 PA_CL_UCP_2_Z
+0x000285E8 PA_CL_UCP_2_W
+0x000285EC PA_CL_UCP_3_X
+0x000285F0 PA_CL_UCP_3_Y
+0x000285F4 PA_CL_UCP_3_Z
+0x000285F8 PA_CL_UCP_3_W
+0x000285FC PA_CL_UCP_4_X
+0x00028600 PA_CL_UCP_4_Y
+0x00028604 PA_CL_UCP_4_Z
+0x00028608 PA_CL_UCP_4_W
+0x0002860C PA_CL_UCP_5_X
+0x00028610 PA_CL_UCP_5_Y
+0x00028614 PA_CL_UCP_5_Z
+0x00028618 PA_CL_UCP_5_W
+0x0002861C SPI_VS_OUT_ID_0
+0x00028620 SPI_VS_OUT_ID_1
+0x00028624 SPI_VS_OUT_ID_2
+0x00028628 SPI_VS_OUT_ID_3
+0x0002862C SPI_VS_OUT_ID_4
+0x00028630 SPI_VS_OUT_ID_5
+0x00028634 SPI_VS_OUT_ID_6
+0x00028638 SPI_VS_OUT_ID_7
+0x0002863C SPI_VS_OUT_ID_8
+0x00028640 SPI_VS_OUT_ID_9
+0x00028644 SPI_PS_INPUT_CNTL_0
+0x00028648 SPI_PS_INPUT_CNTL_1
+0x0002864C SPI_PS_INPUT_CNTL_2
+0x00028650 SPI_PS_INPUT_CNTL_3
+0x00028654 SPI_PS_INPUT_CNTL_4
+0x00028658 SPI_PS_INPUT_CNTL_5
+0x0002865C SPI_PS_INPUT_CNTL_6
+0x00028660 SPI_PS_INPUT_CNTL_7
+0x00028664 SPI_PS_INPUT_CNTL_8
+0x00028668 SPI_PS_INPUT_CNTL_9
+0x0002866C SPI_PS_INPUT_CNTL_10
+0x00028670 SPI_PS_INPUT_CNTL_11
+0x00028674 SPI_PS_INPUT_CNTL_12
+0x00028678 SPI_PS_INPUT_CNTL_13
+0x0002867C SPI_PS_INPUT_CNTL_14
+0x00028680 SPI_PS_INPUT_CNTL_15
+0x00028684 SPI_PS_INPUT_CNTL_16
+0x00028688 SPI_PS_INPUT_CNTL_17
+0x0002868C SPI_PS_INPUT_CNTL_18
+0x00028690 SPI_PS_INPUT_CNTL_19
+0x00028694 SPI_PS_INPUT_CNTL_20
+0x00028698 SPI_PS_INPUT_CNTL_21
+0x0002869C SPI_PS_INPUT_CNTL_22
+0x000286A0 SPI_PS_INPUT_CNTL_23
+0x000286A4 SPI_PS_INPUT_CNTL_24
+0x000286A8 SPI_PS_INPUT_CNTL_25
+0x000286AC SPI_PS_INPUT_CNTL_26
+0x000286B0 SPI_PS_INPUT_CNTL_27
+0x000286B4 SPI_PS_INPUT_CNTL_28
+0x000286B8 SPI_PS_INPUT_CNTL_29
+0x000286BC SPI_PS_INPUT_CNTL_30
+0x000286C0 SPI_PS_INPUT_CNTL_31
+0x000286C4 SPI_VS_OUT_CONFIG
+0x000286C8 SPI_THREAD_GROUPING
+0x000286CC SPI_PS_IN_CONTROL_0
+0x000286D0 SPI_PS_IN_CONTROL_1
+0x000286D4 SPI_INTERP_CONTROL_0
+0x000286D8 SPI_INPUT_Z
+0x000286DC SPI_FOG_CNTL
+0x000286E0 SPI_BARYC_CNTL
+0x000286E4 SPI_PS_IN_CONTROL_2
+0x000286E8 SPI_COMPUTE_INPUT_CNTL
+0x000286EC SPI_COMPUTE_NUM_THREAD_X
+0x000286F0 SPI_COMPUTE_NUM_THREAD_Y
+0x000286F4 SPI_COMPUTE_NUM_THREAD_Z
+0x000286F8 GDS_ADDR_SIZE
+0x00028780 CB_BLEND0_CONTROL
+0x00028784 CB_BLEND1_CONTROL
+0x00028788 CB_BLEND2_CONTROL
+0x0002878C CB_BLEND3_CONTROL
+0x00028790 CB_BLEND4_CONTROL
+0x00028794 CB_BLEND5_CONTROL
+0x00028798 CB_BLEND6_CONTROL
+0x0002879C CB_BLEND7_CONTROL
+0x000287CC CS_COPY_STATE
+0x000287D0 GFX_COPY_STATE
+0x000287D4 PA_CL_POINT_X_RAD
+0x000287D8 PA_CL_POINT_Y_RAD
+0x000287DC PA_CL_POINT_SIZE
+0x000287E0 PA_CL_POINT_CULL_RAD
+0x00028808 CB_COLOR_CONTROL
+0x0002880C DB_SHADER_CONTROL
+0x00028810 PA_CL_CLIP_CNTL
+0x00028814 PA_SU_SC_MODE_CNTL
+0x00028818 PA_CL_VTE_CNTL
+0x0002881C PA_CL_VS_OUT_CNTL
+0x00028820 PA_CL_NANINF_CNTL
+0x00028824 PA_SU_LINE_STIPPLE_CNTL
+0x00028828 PA_SU_LINE_STIPPLE_SCALE
+0x0002882C PA_SU_PRIM_FILTER_CNTL
+0x00028838 SQ_DYN_GPR_RESOURCE_LIMIT_1
+0x00028844 SQ_PGM_RESOURCES_PS
+0x00028848 SQ_PGM_RESOURCES_2_PS
+0x0002884C SQ_PGM_EXPORTS_PS
+0x00028860 SQ_PGM_RESOURCES_VS
+0x00028864 SQ_PGM_RESOURCES_2_VS
+0x00028878 SQ_PGM_RESOURCES_GS
+0x0002887C SQ_PGM_RESOURCES_2_GS
+0x00028890 SQ_PGM_RESOURCES_ES
+0x00028894 SQ_PGM_RESOURCES_2_ES
+0x000288A8 SQ_PGM_RESOURCES_FS
+0x000288BC SQ_PGM_RESOURCES_HS
+0x000288C0 SQ_PGM_RESOURCES_2_HS
+0x000288D4 SQ_PGM_RESOURCES_LS
+0x000288D8 SQ_PGM_RESOURCES_2_LS
+0x000288E8 SQ_LDS_ALLOC
+0x000288EC SQ_LDS_ALLOC_PS
+0x000288F0 SQ_VTX_SEMANTIC_CLEAR
+0x00028A00 PA_SU_POINT_SIZE
+0x00028A04 PA_SU_POINT_MINMAX
+0x00028A08 PA_SU_LINE_CNTL
+0x00028A0C PA_SC_LINE_STIPPLE
+0x00028A10 VGT_OUTPUT_PATH_CNTL
+0x00028A14 VGT_HOS_CNTL
+0x00028A18 VGT_HOS_MAX_TESS_LEVEL
+0x00028A1C VGT_HOS_MIN_TESS_LEVEL
+0x00028A20 VGT_HOS_REUSE_DEPTH
+0x00028A24 VGT_GROUP_PRIM_TYPE
+0x00028A28 VGT_GROUP_FIRST_DECR
+0x00028A2C VGT_GROUP_DECR
+0x00028A30 VGT_GROUP_VECT_0_CNTL
+0x00028A34 VGT_GROUP_VECT_1_CNTL
+0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL
+0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL
+0x00028A40 VGT_GS_MODE
+0x00028A48 PA_SC_MODE_CNTL_0
+0x00028A4C PA_SC_MODE_CNTL_1
+0x00028A50 VGT_ENHANCE
+0x00028A54 VGT_GS_PER_ES
+0x00028A58 VGT_ES_PER_GS
+0x00028A5C VGT_GS_PER_VS
+0x00028A6C VGT_GS_OUT_PRIM_TYPE
+0x00028A84 VGT_PRIMITIVEID_EN
+0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN
+0x00028AA0 VGT_INSTANCE_STEP_RATE_0
+0x00028AA4 VGT_INSTANCE_STEP_RATE_1
+0x00028AB4 VGT_REUSE_OFF
+0x00028AB8 VGT_VTX_CNT_EN
+0x00028ABC DB_HTILE_SURFACE
+0x00028AC0 DB_SRESULTS_COMPARE_STATE0
+0x00028AC4 DB_SRESULTS_COMPARE_STATE1
+0x00028AC8 DB_PRELOAD_CONTROL
+0x00028B38 VGT_GS_MAX_VERT_OUT
+0x00028B54 VGT_SHADER_STAGES_EN
+0x00028B58 VGT_LS_HS_CONFIG
+0x00028B5C VGT_LS_SIZE
+0x00028B60 VGT_HS_SIZE
+0x00028B64 VGT_LS_HS_ALLOC
+0x00028B68 VGT_HS_PATCH_CONST
+0x00028B6C VGT_TF_PARAM
+0x00028B70 DB_ALPHA_TO_MASK
+0x00028B74 VGT_DISPATCH_INITIATOR
+0x00028B78 PA_SU_POLY_OFFSET_DB_FMT_CNTL
+0x00028B7C PA_SU_POLY_OFFSET_CLAMP
+0x00028B80 PA_SU_POLY_OFFSET_FRONT_SCALE
+0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
+0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
+0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
+0x00028B74 VGT_GS_INSTANCE_CNT
+0x00028C00 PA_SC_LINE_CNTL
+0x00028C08 PA_SU_VTX_CNTL
+0x00028C0C PA_CL_GB_VERT_CLIP_ADJ
+0x00028C10 PA_CL_GB_VERT_DISC_ADJ
+0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ
+0x00028C18 PA_CL_GB_HORZ_DISC_ADJ
+0x00028C1C PA_SC_AA_SAMPLE_LOCS_0
+0x00028C20 PA_SC_AA_SAMPLE_LOCS_1
+0x00028C24 PA_SC_AA_SAMPLE_LOCS_2
+0x00028C28 PA_SC_AA_SAMPLE_LOCS_3
+0x00028C2C PA_SC_AA_SAMPLE_LOCS_4
+0x00028C30 PA_SC_AA_SAMPLE_LOCS_5
+0x00028C34 PA_SC_AA_SAMPLE_LOCS_6
+0x00028C38 PA_SC_AA_SAMPLE_LOCS_7
+0x00028C3C PA_SC_AA_MASK
+0x00028C8C CB_COLOR0_CLEAR_WORD0
+0x00028C90 CB_COLOR0_CLEAR_WORD1
+0x00028C94 CB_COLOR0_CLEAR_WORD2
+0x00028C98 CB_COLOR0_CLEAR_WORD3
+0x00028CC8 CB_COLOR1_CLEAR_WORD0
+0x00028CCC CB_COLOR1_CLEAR_WORD1
+0x00028CD0 CB_COLOR1_CLEAR_WORD2
+0x00028CD4 CB_COLOR1_CLEAR_WORD3
+0x00028D04 CB_COLOR2_CLEAR_WORD0
+0x00028D08 CB_COLOR2_CLEAR_WORD1
+0x00028D0C CB_COLOR2_CLEAR_WORD2
+0x00028D10 CB_COLOR2_CLEAR_WORD3
+0x00028D40 CB_COLOR3_CLEAR_WORD0
+0x00028D44 CB_COLOR3_CLEAR_WORD1
+0x00028D48 CB_COLOR3_CLEAR_WORD2
+0x00028D4C CB_COLOR3_CLEAR_WORD3
+0x00028D7C CB_COLOR4_CLEAR_WORD0
+0x00028D80 CB_COLOR4_CLEAR_WORD1
+0x00028D84 CB_COLOR4_CLEAR_WORD2
+0x00028D88 CB_COLOR4_CLEAR_WORD3
+0x00028DB8 CB_COLOR5_CLEAR_WORD0
+0x00028DBC CB_COLOR5_CLEAR_WORD1
+0x00028DC0 CB_COLOR5_CLEAR_WORD2
+0x00028DC4 CB_COLOR5_CLEAR_WORD3
+0x00028DF4 CB_COLOR6_CLEAR_WORD0
+0x00028DF8 CB_COLOR6_CLEAR_WORD1
+0x00028DFC CB_COLOR6_CLEAR_WORD2
+0x00028E00 CB_COLOR6_CLEAR_WORD3
+0x00028E30 CB_COLOR7_CLEAR_WORD0
+0x00028E34 CB_COLOR7_CLEAR_WORD1
+0x00028E38 CB_COLOR7_CLEAR_WORD2
+0x00028E3C CB_COLOR7_CLEAR_WORD3
+0x00028F80 SQ_ALU_CONST_BUFFER_SIZE_HS_0
+0x00028F84 SQ_ALU_CONST_BUFFER_SIZE_HS_1
+0x00028F88 SQ_ALU_CONST_BUFFER_SIZE_HS_2
+0x00028F8C SQ_ALU_CONST_BUFFER_SIZE_HS_3
+0x00028F90 SQ_ALU_CONST_BUFFER_SIZE_HS_4
+0x00028F94 SQ_ALU_CONST_BUFFER_SIZE_HS_5
+0x00028F98 SQ_ALU_CONST_BUFFER_SIZE_HS_6
+0x00028F9C SQ_ALU_CONST_BUFFER_SIZE_HS_7
+0x00028FA0 SQ_ALU_CONST_BUFFER_SIZE_HS_8
+0x00028FA4 SQ_ALU_CONST_BUFFER_SIZE_HS_9
+0x00028FA8 SQ_ALU_CONST_BUFFER_SIZE_HS_10
+0x00028FAC SQ_ALU_CONST_BUFFER_SIZE_HS_11
+0x00028FB0 SQ_ALU_CONST_BUFFER_SIZE_HS_12
+0x00028FB4 SQ_ALU_CONST_BUFFER_SIZE_HS_13
+0x00028FB8 SQ_ALU_CONST_BUFFER_SIZE_HS_14
+0x00028FBC SQ_ALU_CONST_BUFFER_SIZE_HS_15
+0x00028FC0 SQ_ALU_CONST_BUFFER_SIZE_LS_0
+0x00028FC4 SQ_ALU_CONST_BUFFER_SIZE_LS_1
+0x00028FC8 SQ_ALU_CONST_BUFFER_SIZE_LS_2
+0x00028FCC SQ_ALU_CONST_BUFFER_SIZE_LS_3
+0x00028FD0 SQ_ALU_CONST_BUFFER_SIZE_LS_4
+0x00028FD4 SQ_ALU_CONST_BUFFER_SIZE_LS_5
+0x00028FD8 SQ_ALU_CONST_BUFFER_SIZE_LS_6
+0x00028FDC SQ_ALU_CONST_BUFFER_SIZE_LS_7
+0x00028FE0 SQ_ALU_CONST_BUFFER_SIZE_LS_8
+0x00028FE4 SQ_ALU_CONST_BUFFER_SIZE_LS_9
+0x00028FE8 SQ_ALU_CONST_BUFFER_SIZE_LS_10
+0x00028FEC SQ_ALU_CONST_BUFFER_SIZE_LS_11
+0x00028FF0 SQ_ALU_CONST_BUFFER_SIZE_LS_12
+0x00028FF4 SQ_ALU_CONST_BUFFER_SIZE_LS_13
+0x00028FF8 SQ_ALU_CONST_BUFFER_SIZE_LS_14
+0x00028FFC SQ_ALU_CONST_BUFFER_SIZE_LS_15
+0x0003CFF0 SQ_VTX_BASE_VTX_LOC
+0x0003CFF4 SQ_VTX_START_INST_LOC
+0x0003FF00 SQ_TEX_SAMPLER_CLEAR
+0x0003FF04 SQ_TEX_RESOURCE_CLEAR
+0x0003FF08 SQ_LOOP_BOOL_CLEAR
index 79887cac5b54ce19da66e1d5ba3e55df8df07527..7bb4c3e52f3b055ceafc27471e516477e4a3fa5b 100644 (file)
@@ -74,7 +74,8 @@ void rs600_pm_misc(struct radeon_device *rdev)
                        if (voltage->delay)
                                udelay(voltage->delay);
                }
-       }
+       } else if (voltage->type == VOLTAGE_VDDC)
+               radeon_atom_set_voltage(rdev, voltage->vddc_id);
 
        dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH);
        dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf);
index bcc33195ebc2a2e9d2f4e441ed7e88632b5d04bb..f4f0a61bcdce3d188dd01a5737120c4e9a0d6432 100644 (file)
@@ -79,7 +79,13 @@ void rs690_pm_info(struct radeon_device *rdev)
                        tmp.full = dfixed_const(100);
                        rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info.ulBootUpMemoryClock);
                        rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);
-                       rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
+                       if (info->info.usK8MemoryClock)
+                               rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
+                       else if (rdev->clock.default_mclk) {
+                               rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);
+                               rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
+                       } else
+                               rdev->pm.igp_system_mclk.full = dfixed_const(400);
                        rdev->pm.igp_ht_link_clk.full = dfixed_const(le16_to_cpu(info->info.usFSBClock));
                        rdev->pm.igp_ht_link_width.full = dfixed_const(info->info.ucHTLinkWidth);
                        break;
@@ -87,34 +93,31 @@ void rs690_pm_info(struct radeon_device *rdev)
                        tmp.full = dfixed_const(100);
                        rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info_v2.ulBootUpSidePortClock);
                        rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);
-                       rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock);
+                       if (info->info_v2.ulBootUpUMAClock)
+                               rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock);
+                       else if (rdev->clock.default_mclk)
+                               rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);
+                       else
+                               rdev->pm.igp_system_mclk.full = dfixed_const(66700);
                        rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
                        rdev->pm.igp_ht_link_clk.full = dfixed_const(info->info_v2.ulHTLinkFreq);
                        rdev->pm.igp_ht_link_clk.full = dfixed_div(rdev->pm.igp_ht_link_clk, tmp);
                        rdev->pm.igp_ht_link_width.full = dfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth));
                        break;
                default:
-                       tmp.full = dfixed_const(100);
                        /* We assume the slower possible clock ie worst case */
-                       /* DDR 333Mhz */
-                       rdev->pm.igp_sideport_mclk.full = dfixed_const(333);
-                       /* FIXME: system clock ? */
-                       rdev->pm.igp_system_mclk.full = dfixed_const(100);
-                       rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
-                       rdev->pm.igp_ht_link_clk.full = dfixed_const(200);
+                       rdev->pm.igp_sideport_mclk.full = dfixed_const(200);
+                       rdev->pm.igp_system_mclk.full = dfixed_const(200);
+                       rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);
                        rdev->pm.igp_ht_link_width.full = dfixed_const(8);
                        DRM_ERROR("No integrated system info for your GPU, using safe default\n");
                        break;
                }
        } else {
-               tmp.full = dfixed_const(100);
                /* We assume the slower possible clock ie worst case */
-               /* DDR 333Mhz */
-               rdev->pm.igp_sideport_mclk.full = dfixed_const(333);
-               /* FIXME: system clock ? */
-               rdev->pm.igp_system_mclk.full = dfixed_const(100);
-               rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
-               rdev->pm.igp_ht_link_clk.full = dfixed_const(200);
+               rdev->pm.igp_sideport_mclk.full = dfixed_const(200);
+               rdev->pm.igp_system_mclk.full = dfixed_const(200);
+               rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);
                rdev->pm.igp_ht_link_width.full = dfixed_const(8);
                DRM_ERROR("No integrated system info for your GPU, using safe default\n");
        }
@@ -228,10 +231,6 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
        fixed20_12 a, b, c;
        fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
        fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
-       /* FIXME: detect IGP with sideport memory, i don't think there is any
-        * such product available
-        */
-       bool sideport = false;
 
        if (!crtc->base.enabled) {
                /* FIXME: wouldn't it better to set priority mark to maximum */
@@ -300,7 +299,7 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
 
        /* Maximun bandwidth is the minimun bandwidth of all component */
        rdev->pm.max_bandwidth = rdev->pm.core_bandwidth;
-       if (sideport) {
+       if (rdev->mc.igp_sideport_enabled) {
                if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
                        rdev->pm.sideport_bandwidth.full)
                        rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth;
index 253f24aec031e48e1cf2bd99d8595a50275b1f0d..b7fd82064922342d420cacb56a7ece8a00964393 100644 (file)
@@ -44,7 +44,18 @@ void rv770_fini(struct radeon_device *rdev);
 
 void rv770_pm_misc(struct radeon_device *rdev)
 {
-
+       int req_ps_idx = rdev->pm.requested_power_state_index;
+       int req_cm_idx = rdev->pm.requested_clock_mode_index;
+       struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
+       struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
+
+       if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
+               if (voltage->voltage != rdev->pm.current_vddc) {
+                       radeon_atom_set_voltage(rdev, voltage->voltage);
+                       rdev->pm.current_vddc = voltage->voltage;
+                       DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
+               }
+       }
 }
 
 /*
@@ -213,7 +224,7 @@ static void rv770_mc_program(struct radeon_device *rdev)
        WREG32(MC_VM_FB_LOCATION, tmp);
        WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
        WREG32(HDP_NONSURFACE_INFO, (2 << 7));
-       WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
+       WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
        if (rdev->flags & RADEON_IS_AGP) {
                WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
                WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
index 0d9a42c2394f79983344cd8bd21d99204a288109..2f047577b1e391d1d09a9ba4407c0bc3c4b5b4fc 100644 (file)
@@ -77,7 +77,7 @@ struct ttm_page_pool {
 /**
  * Limits for the pool. They are handled without locks because only place where
  * they may change is in sysfs store. They won't have immediate effect anyway
- * so forcing serialiazation to access them is pointless.
+ * so forcing serialization to access them is pointless.
  */
 
 struct ttm_pool_opts {
@@ -165,16 +165,18 @@ static ssize_t ttm_pool_store(struct kobject *kobj,
                m->options.small = val;
        else if (attr == &ttm_page_pool_alloc_size) {
                if (val > NUM_PAGES_TO_ALLOC*8) {
-                       printk(KERN_ERR "[ttm] Setting allocation size to %lu "
-                                       "is not allowed. Recomended size is "
-                                       "%lu\n",
-                                       NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7),
-                                       NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
+                       printk(KERN_ERR TTM_PFX
+                              "Setting allocation size to %lu "
+                              "is not allowed. Recommended size is "
+                              "%lu\n",
+                              NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7),
+                              NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
                        return size;
                } else if (val > NUM_PAGES_TO_ALLOC) {
-                       printk(KERN_WARNING "[ttm] Setting allocation size to "
-                                       "larger than %lu is not recomended.\n",
-                                       NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
+                       printk(KERN_WARNING TTM_PFX
+                              "Setting allocation size to "
+                              "larger than %lu is not recommended.\n",
+                              NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
                }
                m->options.alloc_size = val;
        }
@@ -277,7 +279,7 @@ static void ttm_pages_put(struct page *pages[], unsigned npages)
 {
        unsigned i;
        if (set_pages_array_wb(pages, npages))
-               printk(KERN_ERR "[ttm] Failed to set %d pages to wb!\n",
+               printk(KERN_ERR TTM_PFX "Failed to set %d pages to wb!\n",
                                npages);
        for (i = 0; i < npages; ++i)
                __free_page(pages[i]);
@@ -313,7 +315,8 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
        pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
                        GFP_KERNEL);
        if (!pages_to_free) {
-               printk(KERN_ERR "Failed to allocate memory for pool free operation.\n");
+               printk(KERN_ERR TTM_PFX
+                      "Failed to allocate memory for pool free operation.\n");
                return 0;
        }
 
@@ -390,7 +393,7 @@ static int ttm_pool_get_num_unused_pages(void)
 }
 
 /**
- * Calback for mm to request pool to reduce number of page held.
+ * Callback for mm to request pool to reduce number of page held.
  */
 static int ttm_pool_mm_shrink(int shrink_pages, gfp_t gfp_mask)
 {
@@ -433,14 +436,16 @@ static int ttm_set_pages_caching(struct page **pages,
        case tt_uncached:
                r = set_pages_array_uc(pages, cpages);
                if (r)
-                       printk(KERN_ERR "[ttm] Failed to set %d pages to uc!\n",
-                                       cpages);
+                       printk(KERN_ERR TTM_PFX
+                              "Failed to set %d pages to uc!\n",
+                              cpages);
                break;
        case tt_wc:
                r = set_pages_array_wc(pages, cpages);
                if (r)
-                       printk(KERN_ERR "[ttm] Failed to set %d pages to wc!\n",
-                                       cpages);
+                       printk(KERN_ERR TTM_PFX
+                              "Failed to set %d pages to wc!\n",
+                              cpages);
                break;
        default:
                break;
@@ -458,7 +463,7 @@ static void ttm_handle_caching_state_failure(struct list_head *pages,
                struct page **failed_pages, unsigned cpages)
 {
        unsigned i;
-       /* Failed pages has to be reed */
+       /* Failed pages have to be freed */
        for (i = 0; i < cpages; ++i) {
                list_del(&failed_pages[i]->lru);
                __free_page(failed_pages[i]);
@@ -485,7 +490,8 @@ static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags,
        caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL);
 
        if (!caching_array) {
-               printk(KERN_ERR "[ttm] unable to allocate table for new pages.");
+               printk(KERN_ERR TTM_PFX
+                      "Unable to allocate table for new pages.");
                return -ENOMEM;
        }
 
@@ -493,12 +499,13 @@ static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags,
                p = alloc_page(gfp_flags);
 
                if (!p) {
-                       printk(KERN_ERR "[ttm] unable to get page %u\n", i);
+                       printk(KERN_ERR TTM_PFX "Unable to get page %u.\n", i);
 
                        /* store already allocated pages in the pool after
                         * setting the caching state */
                        if (cpages) {
-                               r = ttm_set_pages_caching(caching_array, cstate, cpages);
+                               r = ttm_set_pages_caching(caching_array,
+                                                         cstate, cpages);
                                if (r)
                                        ttm_handle_caching_state_failure(pages,
                                                ttm_flags, cstate,
@@ -590,7 +597,8 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
                        ++pool->nrefills;
                        pool->npages += alloc_size;
                } else {
-                       printk(KERN_ERR "[ttm] Failed to fill pool (%p).", pool);
+                       printk(KERN_ERR TTM_PFX
+                              "Failed to fill pool (%p).", pool);
                        /* If we have any pages left put them to the pool. */
                        list_for_each_entry(p, &pool->list, lru) {
                                ++cpages;
@@ -659,7 +667,7 @@ int ttm_get_pages(struct list_head *pages, int flags,
 {
        struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
        struct page *p = NULL;
-       int gfp_flags = 0;
+       int gfp_flags = GFP_USER;
        int r;
 
        /* set zero flag for page allocation if required */
@@ -671,13 +679,14 @@ int ttm_get_pages(struct list_head *pages, int flags,
                if (flags & TTM_PAGE_FLAG_DMA32)
                        gfp_flags |= GFP_DMA32;
                else
-                       gfp_flags |= __GFP_HIGHMEM;
+                       gfp_flags |= GFP_HIGHUSER;
 
                for (r = 0; r < count; ++r) {
                        p = alloc_page(gfp_flags);
                        if (!p) {
 
-                               printk(KERN_ERR "[ttm] unable to allocate page.");
+                               printk(KERN_ERR TTM_PFX
+                                      "Unable to allocate page.");
                                return -ENOMEM;
                        }
 
@@ -709,8 +718,9 @@ int ttm_get_pages(struct list_head *pages, int flags,
                if (r) {
                        /* If there is any pages in the list put them back to
                         * the pool. */
-                       printk(KERN_ERR "[ttm] Failed to allocate extra pages "
-                                       "for large request.");
+                       printk(KERN_ERR TTM_PFX
+                              "Failed to allocate extra pages "
+                              "for large request.");
                        ttm_put_pages(pages, 0, flags, cstate);
                        return r;
                }
@@ -778,7 +788,7 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
        if (atomic_add_return(1, &_manager.page_alloc_inited) > 1)
                return 0;
 
-       printk(KERN_INFO "[ttm] Initializing pool allocator.\n");
+       printk(KERN_INFO TTM_PFX "Initializing pool allocator.\n");
 
        ttm_page_pool_init_locked(&_manager.wc_pool, GFP_HIGHUSER, "wc");
 
@@ -813,7 +823,7 @@ void ttm_page_alloc_fini()
        if (atomic_sub_return(1, &_manager.page_alloc_inited) > 0)
                return;
 
-       printk(KERN_INFO "[ttm] Finilizing pool allocator.\n");
+       printk(KERN_INFO TTM_PFX "Finalizing pool allocator.\n");
        ttm_pool_mm_shrink_fini(&_manager);
 
        for (i = 0; i < NUM_POOLS; ++i)
index 1a3cb6816d1cc1a72a58b75a1c4c952e6607c7d3..4505e17df3f557e21beb14581e72f3356985e345 100644 (file)
@@ -4,6 +4,6 @@ ccflags-y := -Iinclude/drm
 vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
            vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
            vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
-           vmwgfx_overlay.o
+           vmwgfx_overlay.o vmwgfx_fence.o
 
 obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
index 0c9c0811f42dd03b9c92d0ea154e249b8ed3b397..b793c8c9acb3162049fabe03b7cf43cfab1939fb 100644 (file)
@@ -88,6 +88,9 @@
 #define DRM_IOCTL_VMW_FENCE_WAIT                               \
        DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT,         \
                 struct drm_vmw_fence_wait_arg)
+#define DRM_IOCTL_VMW_UPDATE_LAYOUT                            \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT,      \
+                struct drm_vmw_update_layout_arg)
 
 
 /**
@@ -135,7 +138,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
                      DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED)
+                     DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(DRM_IOCTL_VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
+                     DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED)
 };
 
 static struct pci_device_id vmw_pci_id_list[] = {
@@ -318,6 +323,15 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                goto out_err3;
        }
 
+       /* Need mmio memory to check for fifo pitchlock cap. */
+       if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
+           !(dev_priv->capabilities & SVGA_CAP_PITCHLOCK) &&
+           !vmw_fifo_have_pitchlock(dev_priv)) {
+               ret = -ENOSYS;
+               DRM_ERROR("Hardware has no pitchlock\n");
+               goto out_err4;
+       }
+
        dev_priv->tdev = ttm_object_device_init
            (dev_priv->mem_global_ref.object, 12);
 
@@ -399,8 +413,6 @@ static int vmw_driver_unload(struct drm_device *dev)
 {
        struct vmw_private *dev_priv = vmw_priv(dev);
 
-       DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n");
-
        unregister_pm_notifier(&dev_priv->pm_nb);
 
        vmw_fb_close(dev_priv);
@@ -546,7 +558,6 @@ static int vmw_master_create(struct drm_device *dev,
 {
        struct vmw_master *vmaster;
 
-       DRM_INFO("Master create.\n");
        vmaster = kzalloc(sizeof(*vmaster), GFP_KERNEL);
        if (unlikely(vmaster == NULL))
                return -ENOMEM;
@@ -563,7 +574,6 @@ static void vmw_master_destroy(struct drm_device *dev,
 {
        struct vmw_master *vmaster = vmw_master(master);
 
-       DRM_INFO("Master destroy.\n");
        master->driver_priv = NULL;
        kfree(vmaster);
 }
@@ -579,8 +589,6 @@ static int vmw_master_set(struct drm_device *dev,
        struct vmw_master *vmaster = vmw_master(file_priv->master);
        int ret = 0;
 
-       DRM_INFO("Master set.\n");
-
        if (active) {
                BUG_ON(active != &dev_priv->fbdev_master);
                ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
@@ -622,8 +630,6 @@ static void vmw_master_drop(struct drm_device *dev,
        struct vmw_master *vmaster = vmw_master(file_priv->master);
        int ret;
 
-       DRM_INFO("Master drop.\n");
-
        /**
         * Make sure the master doesn't disappear while we have
         * it locked.
index 356dc935ec133f974c2c95e2be5d1146cd07c9a9..eaad520953393f5f5da3601627e0ec141c4c4a1f 100644 (file)
 
 #define VMWGFX_DRIVER_DATE "20100209"
 #define VMWGFX_DRIVER_MAJOR 1
-#define VMWGFX_DRIVER_MINOR 0
+#define VMWGFX_DRIVER_MINOR 2
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
 #define VMWGFX_MAX_RELOCATIONS 2048
 #define VMWGFX_MAX_GMRS 2048
+#define VMWGFX_MAX_DISPLAYS 16
 
 struct vmw_fpriv {
        struct drm_master *locked_master;
@@ -102,6 +103,13 @@ struct vmw_surface {
        struct vmw_cursor_snooper snooper;
 };
 
+struct vmw_fence_queue {
+       struct list_head head;
+       struct timespec lag;
+       struct timespec lag_time;
+       spinlock_t lock;
+};
+
 struct vmw_fifo_state {
        unsigned long reserved_size;
        __le32 *dynamic_buffer;
@@ -115,6 +123,7 @@ struct vmw_fifo_state {
        uint32_t capabilities;
        struct mutex fifo_mutex;
        struct rw_semaphore rwsem;
+       struct vmw_fence_queue fence_queue;
 };
 
 struct vmw_relocation {
@@ -144,6 +153,14 @@ struct vmw_master {
        struct ttm_lock lock;
 };
 
+struct vmw_vga_topology_state {
+       uint32_t width;
+       uint32_t height;
+       uint32_t primary;
+       uint32_t pos_x;
+       uint32_t pos_y;
+};
+
 struct vmw_private {
        struct ttm_bo_device bdev;
        struct ttm_bo_global_ref bo_global_ref;
@@ -171,14 +188,19 @@ struct vmw_private {
         * VGA registers.
         */
 
+       struct vmw_vga_topology_state vga_save[VMWGFX_MAX_DISPLAYS];
        uint32_t vga_width;
        uint32_t vga_height;
        uint32_t vga_depth;
        uint32_t vga_bpp;
        uint32_t vga_pseudo;
        uint32_t vga_red_mask;
-       uint32_t vga_blue_mask;
        uint32_t vga_green_mask;
+       uint32_t vga_blue_mask;
+       uint32_t vga_bpl;
+       uint32_t vga_pitchlock;
+
+       uint32_t num_displays;
 
        /*
         * Framebuffer info.
@@ -393,6 +415,7 @@ extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
 extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
 extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
 extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
+extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
 
 /**
  * TTM glue - vmwgfx_ttm_glue.c
@@ -441,6 +464,23 @@ extern int vmw_fallback_wait(struct vmw_private *dev_priv,
                             uint32_t sequence,
                             bool interruptible,
                             unsigned long timeout);
+extern void vmw_update_sequence(struct vmw_private *dev_priv,
+                               struct vmw_fifo_state *fifo_state);
+
+
+/**
+ * Rudimentary fence objects currently used only for throttling -
+ * vmwgfx_fence.c
+ */
+
+extern void vmw_fence_queue_init(struct vmw_fence_queue *queue);
+extern void vmw_fence_queue_takedown(struct vmw_fence_queue *queue);
+extern int vmw_fence_push(struct vmw_fence_queue *queue,
+                         uint32_t sequence);
+extern int vmw_fence_pull(struct vmw_fence_queue *queue,
+                         uint32_t signaled_sequence);
+extern int vmw_wait_lag(struct vmw_private *dev_priv,
+                       struct vmw_fence_queue *queue, uint32_t us);
 
 /**
  * Kernel framebuffer - vmwgfx_fb.c
@@ -466,6 +506,11 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
                          struct ttm_object_file *tfile,
                          struct ttm_buffer_object *bo,
                          SVGA3dCmdHeader *header);
+void vmw_kms_write_svga(struct vmw_private *vmw_priv,
+                       unsigned width, unsigned height, unsigned pitch,
+                       unsigned bbp, unsigned depth);
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
 
 /**
  * Overlay control - vmwgfx_overlay.c
index dbd36b8910cf5cc65f22879c61017f8a0de83dc3..8e396850513cab2b6abebf3858227a7463001121 100644 (file)
@@ -644,6 +644,7 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
        ret = copy_from_user(cmd, user_cmd, arg->command_size);
 
        if (unlikely(ret != 0)) {
+               ret = -EFAULT;
                DRM_ERROR("Failed copying commands.\n");
                goto out_commit;
        }
@@ -669,6 +670,15 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
                goto out_err;
 
        vmw_apply_relocations(sw_context);
+
+       if (arg->throttle_us) {
+               ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.fence_queue,
+                                  arg->throttle_us);
+
+               if (unlikely(ret != 0))
+                       goto out_err;
+       }
+
        vmw_fifo_commit(dev_priv, arg->command_size);
 
        ret = vmw_fifo_send_fence(dev_priv, &sequence);
index 7421aaad8d094e17da75b3b5308d3f491a63e9fa..b0866f04ec7613133a6e4ebc7ab3546906af8258 100644 (file)
@@ -132,16 +132,14 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var,
                return -EINVAL;
        }
 
-       /* without multimon its hard to resize */
-       if (!(vmw_priv->capabilities & SVGA_CAP_MULTIMON) &&
-           (var->xres != par->max_width ||
-            var->yres != par->max_height)) {
-               DRM_ERROR("Tried to resize, but we don't have multimon\n");
+       if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
+           (var->xoffset != 0 || var->yoffset != 0)) {
+               DRM_ERROR("Can not handle panning without display topology\n");
                return -EINVAL;
        }
 
-       if (var->xres > par->max_width ||
-           var->yres > par->max_height) {
+       if ((var->xoffset + var->xres) > par->max_width ||
+           (var->yoffset + var->yres) > par->max_height) {
                DRM_ERROR("Requested geom can not fit in framebuffer\n");
                return -EINVAL;
        }
@@ -154,27 +152,11 @@ static int vmw_fb_set_par(struct fb_info *info)
        struct vmw_fb_par *par = info->par;
        struct vmw_private *vmw_priv = par->vmw_priv;
 
-       if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
-               vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-
-               vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
-               vmw_write(vmw_priv, SVGA_REG_WIDTH, par->max_width);
-               vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height);
-               vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, par->bpp);
-               vmw_write(vmw_priv, SVGA_REG_DEPTH, par->depth);
-               vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
-               vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
-               vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
-
+       vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
+                          info->fix.line_length,
+                          par->bpp, par->depth);
+       if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
                /* TODO check if pitch and offset changes */
-
                vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
@@ -183,13 +165,13 @@ static int vmw_fb_set_par(struct fb_info *info)
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-       } else {
-               vmw_write(vmw_priv, SVGA_REG_WIDTH, info->var.xres);
-               vmw_write(vmw_priv, SVGA_REG_HEIGHT, info->var.yres);
-
-               /* TODO check if pitch and offset changes */
        }
 
+       /* This is really helpful since if this fails the user
+        * can probably not see anything on the screen.
+        */
+       WARN_ON(vmw_read(vmw_priv, SVGA_REG_FB_OFFSET) != 0);
+
        return 0;
 }
 
@@ -416,48 +398,23 @@ int vmw_fb_init(struct vmw_private *vmw_priv)
        unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
        int ret;
 
+       /* XXX These shouldn't be hardcoded. */
        initial_width = 800;
        initial_height = 600;
 
        fb_bbp = 32;
        fb_depth = 24;
 
-       if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
-               fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
-               fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
-       } else {
-               fb_width = min(vmw_priv->fb_max_width, initial_width);
-               fb_height = min(vmw_priv->fb_max_height, initial_height);
-       }
+       /* XXX As shouldn't these be as well. */
+       fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
+       fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
 
        initial_width = min(fb_width, initial_width);
        initial_height = min(fb_height, initial_height);
 
-       vmw_write(vmw_priv, SVGA_REG_WIDTH, fb_width);
-       vmw_write(vmw_priv, SVGA_REG_HEIGHT, fb_height);
-       vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, fb_bbp);
-       vmw_write(vmw_priv, SVGA_REG_DEPTH, fb_depth);
-       vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
-       vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
-       vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
-
-       fb_size = vmw_read(vmw_priv, SVGA_REG_FB_SIZE);
+       fb_pitch = fb_width * fb_bbp / 8;
+       fb_size = fb_pitch * fb_height;
        fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
-       fb_pitch = vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE);
-
-       DRM_DEBUG("width  %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_WIDTH));
-       DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_HEIGHT));
-       DRM_DEBUG("width  %u\n", vmw_read(vmw_priv, SVGA_REG_WIDTH));
-       DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_HEIGHT));
-       DRM_DEBUG("bpp    %u\n", vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL));
-       DRM_DEBUG("depth  %u\n", vmw_read(vmw_priv, SVGA_REG_DEPTH));
-       DRM_DEBUG("bpl    %u\n", vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE));
-       DRM_DEBUG("r mask %08x\n", vmw_read(vmw_priv, SVGA_REG_RED_MASK));
-       DRM_DEBUG("g mask %08x\n", vmw_read(vmw_priv, SVGA_REG_GREEN_MASK));
-       DRM_DEBUG("b mask %08x\n", vmw_read(vmw_priv, SVGA_REG_BLUE_MASK));
-       DRM_DEBUG("fb_offset 0x%08x\n", fb_offset);
-       DRM_DEBUG("fb_pitch  %u\n", fb_pitch);
-       DRM_DEBUG("fb_size   %u kiB\n", fb_size / 1024);
 
        info = framebuffer_alloc(sizeof(*par), device);
        if (!info)
@@ -659,6 +616,10 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
                goto err_unlock;
 
        ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
+
+       /* Could probably bug on */
+       WARN_ON(bo->offset != 0);
+
        ttm_bo_unreserve(bo);
 err_unlock:
        ttm_write_unlock(&vmw_priv->active_master->lock);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
new file mode 100644 (file)
index 0000000..61eacc1
--- /dev/null
@@ -0,0 +1,173 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "vmwgfx_drv.h"
+
+struct vmw_fence {
+       struct list_head head;
+       uint32_t sequence;
+       struct timespec submitted;
+};
+
+void vmw_fence_queue_init(struct vmw_fence_queue *queue)
+{
+       INIT_LIST_HEAD(&queue->head);
+       queue->lag = ns_to_timespec(0);
+       getrawmonotonic(&queue->lag_time);
+       spin_lock_init(&queue->lock);
+}
+
+void vmw_fence_queue_takedown(struct vmw_fence_queue *queue)
+{
+       struct vmw_fence *fence, *next;
+
+       spin_lock(&queue->lock);
+       list_for_each_entry_safe(fence, next, &queue->head, head) {
+               kfree(fence);
+       }
+       spin_unlock(&queue->lock);
+}
+
+int vmw_fence_push(struct vmw_fence_queue *queue,
+                  uint32_t sequence)
+{
+       struct vmw_fence *fence = kmalloc(sizeof(*fence), GFP_KERNEL);
+
+       if (unlikely(!fence))
+               return -ENOMEM;
+
+       fence->sequence = sequence;
+       getrawmonotonic(&fence->submitted);
+       spin_lock(&queue->lock);
+       list_add_tail(&fence->head, &queue->head);
+       spin_unlock(&queue->lock);
+
+       return 0;
+}
+
+int vmw_fence_pull(struct vmw_fence_queue *queue,
+                  uint32_t signaled_sequence)
+{
+       struct vmw_fence *fence, *next;
+       struct timespec now;
+       bool updated = false;
+
+       spin_lock(&queue->lock);
+       getrawmonotonic(&now);
+
+       if (list_empty(&queue->head)) {
+               queue->lag = ns_to_timespec(0);
+               queue->lag_time = now;
+               updated = true;
+               goto out_unlock;
+       }
+
+       list_for_each_entry_safe(fence, next, &queue->head, head) {
+               if (signaled_sequence - fence->sequence > (1 << 30))
+                       continue;
+
+               queue->lag = timespec_sub(now, fence->submitted);
+               queue->lag_time = now;
+               updated = true;
+               list_del(&fence->head);
+               kfree(fence);
+       }
+
+out_unlock:
+       spin_unlock(&queue->lock);
+
+       return (updated) ? 0 : -EBUSY;
+}
+
+static struct timespec vmw_timespec_add(struct timespec t1,
+                                       struct timespec t2)
+{
+       t1.tv_sec += t2.tv_sec;
+       t1.tv_nsec += t2.tv_nsec;
+       if (t1.tv_nsec >= 1000000000L) {
+               t1.tv_sec += 1;
+               t1.tv_nsec -= 1000000000L;
+       }
+
+       return t1;
+}
+
+static struct timespec vmw_fifo_lag(struct vmw_fence_queue *queue)
+{
+       struct timespec now;
+
+       spin_lock(&queue->lock);
+       getrawmonotonic(&now);
+       queue->lag = vmw_timespec_add(queue->lag,
+                                     timespec_sub(now, queue->lag_time));
+       queue->lag_time = now;
+       spin_unlock(&queue->lock);
+       return queue->lag;
+}
+
+
+static bool vmw_lag_lt(struct vmw_fence_queue *queue,
+                      uint32_t us)
+{
+       struct timespec lag, cond;
+
+       cond = ns_to_timespec((s64) us * 1000);
+       lag = vmw_fifo_lag(queue);
+       return (timespec_compare(&lag, &cond) < 1);
+}
+
+int vmw_wait_lag(struct vmw_private *dev_priv,
+                struct vmw_fence_queue *queue, uint32_t us)
+{
+       struct vmw_fence *fence;
+       uint32_t sequence;
+       int ret;
+
+       while (!vmw_lag_lt(queue, us)) {
+               spin_lock(&queue->lock);
+               if (list_empty(&queue->head))
+                       sequence = atomic_read(&dev_priv->fence_seq);
+               else {
+                       fence = list_first_entry(&queue->head,
+                                                struct vmw_fence, head);
+                       sequence = fence->sequence;
+               }
+               spin_unlock(&queue->lock);
+
+               ret = vmw_wait_fence(dev_priv, false, sequence, true,
+                                    3*HZ);
+
+               if (unlikely(ret != 0))
+                       return ret;
+
+               (void) vmw_fence_pull(queue, sequence);
+       }
+       return 0;
+}
+
+
index 39d43a01d846fd9e7bcd6a1206b06143f90a740d..e6a1eb7ea95498f00e65d123adeae79160af8fa8 100644 (file)
@@ -34,6 +34,9 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
        __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
        uint32_t fifo_min, hwversion;
 
+       if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
+               return false;
+
        fifo_min = ioread32(fifo_mem  + SVGA_FIFO_MIN);
        if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
                return false;
@@ -48,6 +51,21 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
        return true;
 }
 
+bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
+{
+       __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+       uint32_t caps;
+
+       if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
+               return false;
+
+       caps = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
+       if (caps & SVGA_FIFO_CAP_PITCHLOCK)
+               return true;
+
+       return false;
+}
+
 int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
 {
        __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
@@ -120,7 +138,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
 
        atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence);
        iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
-
+       vmw_fence_queue_init(&fifo->fence_queue);
        return vmw_fifo_send_fence(dev_priv, &dummy);
 out_err:
        vfree(fifo->static_buffer);
@@ -159,6 +177,7 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
                  dev_priv->enable_state);
 
        mutex_unlock(&dev_priv->hw_mutex);
+       vmw_fence_queue_takedown(&fifo->fence_queue);
 
        if (likely(fifo->last_buffer != NULL)) {
                vfree(fifo->last_buffer);
@@ -484,6 +503,8 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
        fifo_state->last_buffer_add = true;
        vmw_fifo_commit(dev_priv, bytes);
        fifo_state->last_buffer_add = false;
+       (void) vmw_fence_push(&fifo_state->fence_queue, *sequence);
+       vmw_update_sequence(dev_priv, fifo_state);
 
 out_err:
        return ret;
index 4d7cb539386000b50798960f8615d2fc2b25d2ba..e92298a6a383c1fe60c290002a33a3e39caa456f 100644 (file)
@@ -64,22 +64,33 @@ static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t sequence)
        return (busy == 0);
 }
 
+void vmw_update_sequence(struct vmw_private *dev_priv,
+                        struct vmw_fifo_state *fifo_state)
+{
+       __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+
+       uint32_t sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+
+       if (dev_priv->last_read_sequence != sequence) {
+               dev_priv->last_read_sequence = sequence;
+               vmw_fence_pull(&fifo_state->fence_queue, sequence);
+       }
+}
 
 bool vmw_fence_signaled(struct vmw_private *dev_priv,
                        uint32_t sequence)
 {
-       __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
        struct vmw_fifo_state *fifo_state;
        bool ret;
 
        if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
                return true;
 
-       dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+       fifo_state = &dev_priv->fifo;
+       vmw_update_sequence(dev_priv, fifo_state);
        if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
                return true;
 
-       fifo_state = &dev_priv->fifo;
        if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) &&
            vmw_fifo_idle(dev_priv, sequence))
                return true;
index bbc7c4c30bc7fc26d6c2244ba53ab70324af1593..f1d62611241586f73115a0a8cd60f853837308f6 100644 (file)
@@ -30,6 +30,8 @@
 /* Might need a hrtimer here? */
 #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
 
+static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb);
+static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb);
 
 void vmw_display_unit_cleanup(struct vmw_display_unit *du)
 {
@@ -326,6 +328,7 @@ int vmw_framebuffer_create_handle(struct drm_framebuffer *fb,
 struct vmw_framebuffer_surface {
        struct vmw_framebuffer base;
        struct vmw_surface *surface;
+       struct vmw_dma_buffer *buffer;
        struct delayed_work d_work;
        struct mutex work_lock;
        bool present_fs;
@@ -500,8 +503,8 @@ int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
        vfbs->base.base.depth = 24;
        vfbs->base.base.width = width;
        vfbs->base.base.height = height;
-       vfbs->base.pin = NULL;
-       vfbs->base.unpin = NULL;
+       vfbs->base.pin = &vmw_surface_dmabuf_pin;
+       vfbs->base.unpin = &vmw_surface_dmabuf_unpin;
        vfbs->surface = surface;
        mutex_init(&vfbs->work_lock);
        INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback);
@@ -589,6 +592,40 @@ static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = {
        .create_handle = vmw_framebuffer_create_handle,
 };
 
+static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb)
+{
+       struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
+       struct vmw_framebuffer_surface *vfbs =
+               vmw_framebuffer_to_vfbs(&vfb->base);
+       unsigned long size = vfbs->base.base.pitch * vfbs->base.base.height;
+       int ret;
+
+       vfbs->buffer = kzalloc(sizeof(*vfbs->buffer), GFP_KERNEL);
+       if (unlikely(vfbs->buffer == NULL))
+               return -ENOMEM;
+
+       vmw_overlay_pause_all(dev_priv);
+       ret = vmw_dmabuf_init(dev_priv, vfbs->buffer, size,
+                              &vmw_vram_ne_placement,
+                              false, &vmw_dmabuf_bo_free);
+       vmw_overlay_resume_all(dev_priv);
+
+       return ret;
+}
+
+static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb)
+{
+       struct ttm_buffer_object *bo;
+       struct vmw_framebuffer_surface *vfbs =
+               vmw_framebuffer_to_vfbs(&vfb->base);
+
+       bo = &vfbs->buffer->base;
+       ttm_bo_unref(&bo);
+       vfbs->buffer = NULL;
+
+       return 0;
+}
+
 static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
 {
        struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
@@ -596,33 +633,15 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
                vmw_framebuffer_to_vfbd(&vfb->base);
        int ret;
 
+
        vmw_overlay_pause_all(dev_priv);
 
        ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
 
-       if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
-               vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-
-               vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
-               vmw_write(dev_priv, SVGA_REG_WIDTH, vfb->base.width);
-               vmw_write(dev_priv, SVGA_REG_HEIGHT, vfb->base.height);
-               vmw_write(dev_priv, SVGA_REG_BITS_PER_PIXEL, vfb->base.bits_per_pixel);
-               vmw_write(dev_priv, SVGA_REG_DEPTH, vfb->base.depth);
-               vmw_write(dev_priv, SVGA_REG_RED_MASK, 0x00ff0000);
-               vmw_write(dev_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
-               vmw_write(dev_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
-       } else
-               WARN_ON(true);
-
        vmw_overlay_resume_all(dev_priv);
 
+       WARN_ON(ret != 0);
+
        return 0;
 }
 
@@ -668,7 +687,7 @@ int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
 
        /* XXX get the first 3 from the surface info */
        vfbd->base.base.bits_per_pixel = 32;
-       vfbd->base.base.pitch = width * 32 / 4;
+       vfbd->base.base.pitch = width * vfbd->base.base.bits_per_pixel / 8;
        vfbd->base.base.depth = 24;
        vfbd->base.base.width = width;
        vfbd->base.base.height = height;
@@ -765,8 +784,9 @@ int vmw_kms_init(struct vmw_private *dev_priv)
        dev->mode_config.funcs = &vmw_kms_funcs;
        dev->mode_config.min_width = 1;
        dev->mode_config.min_height = 1;
-       dev->mode_config.max_width = dev_priv->fb_max_width;
-       dev->mode_config.max_height = dev_priv->fb_max_height;
+       /* assumed largest fb size */
+       dev->mode_config.max_width = 8192;
+       dev->mode_config.max_height = 8192;
 
        ret = vmw_kms_init_legacy_display_system(dev_priv);
 
@@ -826,49 +846,140 @@ out:
        return ret;
 }
 
+void vmw_kms_write_svga(struct vmw_private *vmw_priv,
+                       unsigned width, unsigned height, unsigned pitch,
+                       unsigned bbp, unsigned depth)
+{
+       if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+               vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch);
+       else if (vmw_fifo_have_pitchlock(vmw_priv))
+               iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+       vmw_write(vmw_priv, SVGA_REG_WIDTH, width);
+       vmw_write(vmw_priv, SVGA_REG_HEIGHT, height);
+       vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bbp);
+       vmw_write(vmw_priv, SVGA_REG_DEPTH, depth);
+       vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
+       vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
+       vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+}
+
 int vmw_kms_save_vga(struct vmw_private *vmw_priv)
 {
-       /*
-        * setup a single multimon monitor with the size
-        * of 0x0, this stops the UI from resizing when we
-        * change the framebuffer size
-        */
-       if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
-               vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-       }
+       struct vmw_vga_topology_state *save;
+       uint32_t i;
 
        vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
        vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
-       vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
        vmw_priv->vga_depth = vmw_read(vmw_priv, SVGA_REG_DEPTH);
+       vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
        vmw_priv->vga_pseudo = vmw_read(vmw_priv, SVGA_REG_PSEUDOCOLOR);
        vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
-       vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
        vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
+       vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
+       if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+               vmw_priv->vga_pitchlock =
+                 vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
+       else if (vmw_fifo_have_pitchlock(vmw_priv))
+               vmw_priv->vga_pitchlock = ioread32(vmw_priv->mmio_virt +
+                                                      SVGA_FIFO_PITCHLOCK);
+
+       if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
+               return 0;
 
+       vmw_priv->num_displays = vmw_read(vmw_priv,
+                                         SVGA_REG_NUM_GUEST_DISPLAYS);
+
+       for (i = 0; i < vmw_priv->num_displays; ++i) {
+               save = &vmw_priv->vga_save[i];
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i);
+               save->primary = vmw_read(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY);
+               save->pos_x = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_X);
+               save->pos_y = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y);
+               save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
+               save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+       }
        return 0;
 }
 
 int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
 {
+       struct vmw_vga_topology_state *save;
+       uint32_t i;
+
        vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width);
        vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height);
-       vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
        vmw_write(vmw_priv, SVGA_REG_DEPTH, vmw_priv->vga_depth);
+       vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
        vmw_write(vmw_priv, SVGA_REG_PSEUDOCOLOR, vmw_priv->vga_pseudo);
        vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
        vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
        vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
+       if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+               vmw_write(vmw_priv, SVGA_REG_PITCHLOCK,
+                         vmw_priv->vga_pitchlock);
+       else if (vmw_fifo_have_pitchlock(vmw_priv))
+               iowrite32(vmw_priv->vga_pitchlock,
+                         vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+
+       if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
+               return 0;
 
-       /* TODO check for multimon */
-       vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
+       for (i = 0; i < vmw_priv->num_displays; ++i) {
+               save = &vmw_priv->vga_save[i];
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, save->primary);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, save->pos_x);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, save->pos_y);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, save->width);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, save->height);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+       }
 
        return 0;
 }
+
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+{
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       struct drm_vmw_update_layout_arg *arg =
+               (struct drm_vmw_update_layout_arg *)data;
+       struct vmw_master *vmaster = vmw_master(file_priv->master);
+       void __user *user_rects;
+       struct drm_vmw_rect *rects;
+       unsigned rects_size;
+       int ret;
+
+       ret = ttm_read_lock(&vmaster->lock, true);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (!arg->num_outputs) {
+               struct drm_vmw_rect def_rect = {0, 0, 800, 600};
+               vmw_kms_ldu_update_layout(dev_priv, 1, &def_rect);
+               goto out_unlock;
+       }
+
+       rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
+       rects = kzalloc(rects_size, GFP_KERNEL);
+       if (unlikely(!rects)) {
+               ret = -ENOMEM;
+               goto out_unlock;
+       }
+
+       user_rects = (void __user *)(unsigned long)arg->rects;
+       ret = copy_from_user(rects, user_rects, rects_size);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Failed to get rects.\n");
+               goto out_free;
+       }
+
+       vmw_kms_ldu_update_layout(dev_priv, arg->num_outputs, rects);
+
+out_free:
+       kfree(rects);
+out_unlock:
+       ttm_read_unlock(&vmaster->lock);
+       return ret;
+}
index 8b95249f0531ab0767f9248daee39063874d024f..8a398a0339b6c82a2c86178eb8d7657f80212964 100644 (file)
@@ -94,9 +94,11 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
 int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
 
 /*
- * Legacy display unit functions - vmwgfx_ldu.h
+ * Legacy display unit functions - vmwgfx_ldu.c
  */
 int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
 int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
+int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
+                             struct drm_vmw_rect *rects);
 
 #endif
index 90891593bf6c2ea01cc23ab52d03452cb5d99c08..cfaf690a5b2f423d6f150800cfb2d655d272a0bc 100644 (file)
@@ -38,6 +38,7 @@ struct vmw_legacy_display {
        struct list_head active;
 
        unsigned num_active;
+       unsigned last_num_active;
 
        struct vmw_framebuffer *fb;
 };
@@ -48,9 +49,12 @@ struct vmw_legacy_display {
 struct vmw_legacy_display_unit {
        struct vmw_display_unit base;
 
-       struct list_head active;
+       unsigned pref_width;
+       unsigned pref_height;
+       bool pref_active;
+       struct drm_display_mode *pref_mode;
 
-       unsigned unit;
+       struct list_head active;
 };
 
 static void vmw_ldu_destroy(struct vmw_legacy_display_unit *ldu)
@@ -88,23 +92,44 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
 {
        struct vmw_legacy_display *lds = dev_priv->ldu_priv;
        struct vmw_legacy_display_unit *entry;
-       struct drm_crtc *crtc;
+       struct drm_framebuffer *fb = NULL;
+       struct drm_crtc *crtc = NULL;
        int i = 0;
 
-       /* to stop the screen from changing size on resize */
-       vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
-       for (i = 0; i < lds->num_active; i++) {
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+       /* If there is no display topology the host just assumes
+        * that the guest will set the same layout as the host.
+        */
+       if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) {
+               int w = 0, h = 0;
+               list_for_each_entry(entry, &lds->active, active) {
+                       crtc = &entry->base.crtc;
+                       w = max(w, crtc->x + crtc->mode.hdisplay);
+                       h = max(h, crtc->y + crtc->mode.vdisplay);
+                       i++;
+               }
+
+               if (crtc == NULL)
+                       return 0;
+               fb = entry->base.crtc.fb;
+
+               vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
+                                  fb->bits_per_pixel, fb->depth);
+
+               return 0;
        }
 
-       /* Now set the mode */
-       vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active);
+       if (!list_empty(&lds->active)) {
+               entry = list_entry(lds->active.next, typeof(*entry), active);
+               fb = entry->base.crtc.fb;
+
+               vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitch,
+                                  fb->bits_per_pixel, fb->depth);
+       }
+
+       /* Make sure we always show something. */
+       vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS,
+                 lds->num_active ? lds->num_active : 1);
+
        i = 0;
        list_for_each_entry(entry, &lds->active, active) {
                crtc = &entry->base.crtc;
@@ -120,6 +145,10 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
                i++;
        }
 
+       BUG_ON(i != lds->num_active);
+
+       lds->last_num_active = lds->num_active;
+
        return 0;
 }
 
@@ -130,6 +159,7 @@ static int vmw_ldu_del_active(struct vmw_private *vmw_priv,
        if (list_empty(&ldu->active))
                return 0;
 
+       /* Must init otherwise list_empty(&ldu->active) will not work. */
        list_del_init(&ldu->active);
        if (--(ld->num_active) == 0) {
                BUG_ON(!ld->fb);
@@ -149,24 +179,29 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
        struct vmw_legacy_display_unit *entry;
        struct list_head *at;
 
+       BUG_ON(!ld->num_active && ld->fb);
+       if (vfb != ld->fb) {
+               if (ld->fb && ld->fb->unpin)
+                       ld->fb->unpin(ld->fb);
+               if (vfb->pin)
+                       vfb->pin(vfb);
+               ld->fb = vfb;
+       }
+
        if (!list_empty(&ldu->active))
                return 0;
 
        at = &ld->active;
        list_for_each_entry(entry, &ld->active, active) {
-               if (entry->unit > ldu->unit)
+               if (entry->base.unit > ldu->base.unit)
                        break;
 
                at = &entry->active;
        }
 
        list_add(&ldu->active, at);
-       if (ld->num_active++ == 0) {
-               BUG_ON(ld->fb);
-               if (vfb->pin)
-                       vfb->pin(vfb);
-               ld->fb = vfb;
-       }
+
+       ld->num_active++;
 
        return 0;
 }
@@ -208,6 +243,8 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 
        /* ldu only supports one fb active at the time */
        if (dev_priv->ldu_priv->fb && vfb &&
+           !(dev_priv->ldu_priv->num_active == 1 &&
+             !list_empty(&ldu->active)) &&
            dev_priv->ldu_priv->fb != vfb) {
                DRM_ERROR("Multiple framebuffers not supported\n");
                return -EINVAL;
@@ -300,8 +337,7 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector)
 static enum drm_connector_status
        vmw_ldu_connector_detect(struct drm_connector *connector)
 {
-       /* XXX vmwctrl should control connection status */
-       if (vmw_connector_to_ldu(connector)->base.unit == 0)
+       if (vmw_connector_to_ldu(connector)->pref_active)
                return connector_status_connected;
        return connector_status_disconnected;
 }
@@ -312,10 +348,9 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
                   752, 800, 0, 480, 489, 492, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 800x600@60Hz */
-       { DRM_MODE("800x600",
-                  DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
-                  40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628,
-                  0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
+                  968, 1056, 0, 600, 601, 605, 628, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
        /* 1024x768@60Hz */
        { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
                   1184, 1344, 0, 768, 771, 777, 806, 0,
@@ -387,10 +422,34 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
 static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
                                        uint32_t max_width, uint32_t max_height)
 {
+       struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
        struct drm_device *dev = connector->dev;
        struct drm_display_mode *mode = NULL;
+       struct drm_display_mode prefmode = { DRM_MODE("preferred",
+               DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
+       };
        int i;
 
+       /* Add preferred mode */
+       {
+               mode = drm_mode_duplicate(dev, &prefmode);
+               if (!mode)
+                       return 0;
+               mode->hdisplay = ldu->pref_width;
+               mode->vdisplay = ldu->pref_height;
+               mode->vrefresh = drm_mode_vrefresh(mode);
+               drm_mode_probed_add(connector, mode);
+
+               if (ldu->pref_mode) {
+                       list_del_init(&ldu->pref_mode->head);
+                       drm_mode_destroy(dev, ldu->pref_mode);
+               }
+
+               ldu->pref_mode = mode;
+       }
+
        for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
                if (vmw_ldu_connector_builtin[i].hdisplay > max_width ||
                    vmw_ldu_connector_builtin[i].vdisplay > max_height)
@@ -443,18 +502,21 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
        if (!ldu)
                return -ENOMEM;
 
-       ldu->unit = unit;
+       ldu->base.unit = unit;
        crtc = &ldu->base.crtc;
        encoder = &ldu->base.encoder;
        connector = &ldu->base.connector;
 
+       INIT_LIST_HEAD(&ldu->active);
+
+       ldu->pref_active = (unit == 0);
+       ldu->pref_width = 800;
+       ldu->pref_height = 600;
+       ldu->pref_mode = NULL;
+
        drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
                           DRM_MODE_CONNECTOR_LVDS);
-       /* Initial status */
-       if (unit == 0)
-               connector->status = connector_status_connected;
-       else
-               connector->status = connector_status_disconnected;
+       connector->status = vmw_ldu_connector_detect(connector);
 
        drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
                         DRM_MODE_ENCODER_LVDS);
@@ -462,8 +524,6 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
        encoder->possible_crtcs = (1 << unit);
        encoder->possible_clones = 0;
 
-       INIT_LIST_HEAD(&ldu->active);
-
        drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
 
        drm_connector_attach_property(connector,
@@ -487,18 +547,22 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
 
        INIT_LIST_HEAD(&dev_priv->ldu_priv->active);
        dev_priv->ldu_priv->num_active = 0;
+       dev_priv->ldu_priv->last_num_active = 0;
        dev_priv->ldu_priv->fb = NULL;
 
        drm_mode_create_dirty_info_property(dev_priv->dev);
 
        vmw_ldu_init(dev_priv, 0);
-       vmw_ldu_init(dev_priv, 1);
-       vmw_ldu_init(dev_priv, 2);
-       vmw_ldu_init(dev_priv, 3);
-       vmw_ldu_init(dev_priv, 4);
-       vmw_ldu_init(dev_priv, 5);
-       vmw_ldu_init(dev_priv, 6);
-       vmw_ldu_init(dev_priv, 7);
+       /* for old hardware without multimon only enable one display */
+       if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
+               vmw_ldu_init(dev_priv, 1);
+               vmw_ldu_init(dev_priv, 2);
+               vmw_ldu_init(dev_priv, 3);
+               vmw_ldu_init(dev_priv, 4);
+               vmw_ldu_init(dev_priv, 5);
+               vmw_ldu_init(dev_priv, 6);
+               vmw_ldu_init(dev_priv, 7);
+       }
 
        return 0;
 }
@@ -514,3 +578,42 @@ int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
 
        return 0;
 }
+
+int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
+                             struct drm_vmw_rect *rects)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct vmw_legacy_display_unit *ldu;
+       struct drm_connector *con;
+       int i;
+
+       mutex_lock(&dev->mode_config.mutex);
+
+#if 0
+       DRM_INFO("%s: new layout ", __func__);
+       for (i = 0; i < (int)num; i++)
+               DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
+                        rects[i].w, rects[i].h);
+       DRM_INFO("\n");
+#else
+       (void)i;
+#endif
+
+       list_for_each_entry(con, &dev->mode_config.connector_list, head) {
+               ldu = vmw_connector_to_ldu(con);
+               if (num > ldu->base.unit) {
+                       ldu->pref_width = rects[ldu->base.unit].w;
+                       ldu->pref_height = rects[ldu->base.unit].h;
+                       ldu->pref_active = true;
+               } else {
+                       ldu->pref_width = 800;
+                       ldu->pref_height = 600;
+                       ldu->pref_active = false;
+               }
+               con->status = vmw_ldu_connector_detect(con);
+       }
+
+       mutex_unlock(&dev->mode_config.mutex);
+
+       return 0;
+}
index ad566c85b075da13305ecef856b254ff4dc30a6b..df2036ed18d5f2c920ba61f99b716998a6f25329 100644 (file)
@@ -358,6 +358,8 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv,
        if (stream->buf != buf)
                stream->buf = vmw_dmabuf_reference(buf);
        stream->saved = *arg;
+       /* stream is no longer stopped/paused */
+       stream->paused = false;
 
        return 0;
 }
index f8fbbc67a40675d29418f0cd6ed7f99213c9fb1c..8612378b131edba7589099226d51e594863e5c42 100644 (file)
@@ -597,8 +597,10 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
 
        ret = copy_from_user(srf->sizes, user_sizes,
                             srf->num_sizes * sizeof(*srf->sizes));
-       if (unlikely(ret != 0))
+       if (unlikely(ret != 0)) {
+               ret = -EFAULT;
                goto out_err1;
+       }
 
        if (srf->scanout &&
            srf->num_sizes == 1 &&
@@ -697,9 +699,11 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
        if (user_sizes)
                ret = copy_to_user(user_sizes, srf->sizes,
                                   srf->num_sizes * sizeof(*srf->sizes));
-       if (unlikely(ret != 0))
+       if (unlikely(ret != 0)) {
                DRM_ERROR("copy_to_user failed %p %u\n",
                          user_sizes, srf->num_sizes);
+               ret = -EFAULT;
+       }
 out_bad_resource:
 out_no_reference:
        ttm_base_object_unref(&base);
index 441e38c95a8535b863d924aea1c468872ba6d27a..b87569e96b163c04fb35790ef8c457999480e3f3 100644 (file)
@@ -1,12 +1,32 @@
 /*
- * vgaarb.c
+ * vgaarb.c: Implements the VGA arbitration. For details refer to
+ * Documentation/vgaarbiter.txt
+ *
  *
  * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
  * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
  * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
  *
- * Implements the VGA arbitration. For details refer to
- * Documentation/vgaarbiter.txt
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS
+ * IN THE SOFTWARE.
+ *
  */
 
 #include <linux/module.h>
@@ -155,8 +175,8 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
            (vgadev->decodes & VGA_RSRC_LEGACY_MEM))
                rsrc |= VGA_RSRC_LEGACY_MEM;
 
-       pr_devel("%s: %d\n", __func__, rsrc);
-       pr_devel("%s: owns: %d\n", __func__, vgadev->owns);
+       pr_debug("%s: %d\n", __func__, rsrc);
+       pr_debug("%s: owns: %d\n", __func__, vgadev->owns);
 
        /* Check what resources we need to acquire */
        wants = rsrc & ~vgadev->owns;
@@ -268,7 +288,7 @@ static void __vga_put(struct vga_device *vgadev, unsigned int rsrc)
 {
        unsigned int old_locks = vgadev->locks;
 
-       pr_devel("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        /* Update our counters, and account for equivalent legacy resources
         * if we decode them
@@ -575,6 +595,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
                else
                        vga_decode_count--;
        }
+       pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count);
 }
 
 void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace)
@@ -831,7 +852,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                curr_pos += 5;
                remaining -= 5;
 
-               pr_devel("client 0x%p called 'lock'\n", priv);
+               pr_debug("client 0x%p called 'lock'\n", priv);
 
                if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
                        ret_val = -EPROTO;
@@ -867,7 +888,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                curr_pos += 7;
                remaining -= 7;
 
-               pr_devel("client 0x%p called 'unlock'\n", priv);
+               pr_debug("client 0x%p called 'unlock'\n", priv);
 
                if (strncmp(curr_pos, "all", 3) == 0)
                        io_state = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
@@ -917,7 +938,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                curr_pos += 8;
                remaining -= 8;
 
-               pr_devel("client 0x%p called 'trylock'\n", priv);
+               pr_debug("client 0x%p called 'trylock'\n", priv);
 
                if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
                        ret_val = -EPROTO;
@@ -961,7 +982,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
 
                curr_pos += 7;
                remaining -= 7;
-               pr_devel("client 0x%p called 'target'\n", priv);
+               pr_debug("client 0x%p called 'target'\n", priv);
                /* if target is default */
                if (!strncmp(curr_pos, "default", 7))
                        pdev = pci_dev_get(vga_default_device());
@@ -971,11 +992,11 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                                ret_val = -EPROTO;
                                goto done;
                        }
-                       pr_devel("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
+                       pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
                                domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
 
                        pbus = pci_find_bus(domain, bus);
-                       pr_devel("vgaarb: pbus %p\n", pbus);
+                       pr_debug("vgaarb: pbus %p\n", pbus);
                        if (pbus == NULL) {
                                pr_err("vgaarb: invalid PCI domain and/or bus address %x:%x\n",
                                        domain, bus);
@@ -983,7 +1004,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                                goto done;
                        }
                        pdev = pci_get_slot(pbus, devfn);
-                       pr_devel("vgaarb: pdev %p\n", pdev);
+                       pr_debug("vgaarb: pdev %p\n", pdev);
                        if (!pdev) {
                                pr_err("vgaarb: invalid PCI address %x:%x\n",
                                        bus, devfn);
@@ -993,7 +1014,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                }
 
                vgadev = vgadev_find(pdev);
-               pr_devel("vgaarb: vgadev %p\n", vgadev);
+               pr_debug("vgaarb: vgadev %p\n", vgadev);
                if (vgadev == NULL) {
                        pr_err("vgaarb: this pci device is not a vga device\n");
                        pci_dev_put(pdev);
@@ -1029,7 +1050,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
        } else if (strncmp(curr_pos, "decodes ", 8) == 0) {
                curr_pos += 8;
                remaining -= 8;
-               pr_devel("vgaarb: client 0x%p called 'decodes'\n", priv);
+               pr_debug("vgaarb: client 0x%p called 'decodes'\n", priv);
 
                if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
                        ret_val = -EPROTO;
@@ -1058,7 +1079,7 @@ static unsigned int vga_arb_fpoll(struct file *file, poll_table * wait)
 {
        struct vga_arb_private *priv = file->private_data;
 
-       pr_devel("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        if (priv == NULL)
                return -ENODEV;
@@ -1071,7 +1092,7 @@ static int vga_arb_open(struct inode *inode, struct file *file)
        struct vga_arb_private *priv;
        unsigned long flags;
 
-       pr_devel("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        priv = kmalloc(sizeof(struct vga_arb_private), GFP_KERNEL);
        if (priv == NULL)
@@ -1101,7 +1122,7 @@ static int vga_arb_release(struct inode *inode, struct file *file)
        unsigned long flags;
        int i;
 
-       pr_devel("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        if (priv == NULL)
                return -ENODEV;
@@ -1112,7 +1133,7 @@ static int vga_arb_release(struct inode *inode, struct file *file)
                uc = &priv->cards[i];
                if (uc->pdev == NULL)
                        continue;
-               pr_devel("uc->io_cnt == %d, uc->mem_cnt == %d\n",
+               pr_debug("uc->io_cnt == %d, uc->mem_cnt == %d\n",
                         uc->io_cnt, uc->mem_cnt);
                while (uc->io_cnt--)
                        vga_put(uc->pdev, VGA_RSRC_LEGACY_IO);
@@ -1165,7 +1186,7 @@ static int pci_notify(struct notifier_block *nb, unsigned long action,
        struct pci_dev *pdev = to_pci_dev(dev);
        bool notify = false;
 
-       pr_devel("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        /* For now we're only intereted in devices added and removed. I didn't
         * test this thing here, so someone needs to double check for the
index 4086c7257f912f23608c261f1b29f68b3c04a602..f13c843a2964bbb07728c06363cda065937293bb 100644 (file)
@@ -316,7 +316,6 @@ static int __devinit adt7411_probe(struct i2c_client *client,
  exit_remove:
        sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
  exit_free:
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return ret;
 }
@@ -327,7 +326,6 @@ static int __devexit adt7411_remove(struct i2c_client *client)
 
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return 0;
 }
index 0f388adc61876cc3f0481de786289d724b1977a6..3b973f30b1f6495a89029b4002816ee8ff299353 100644 (file)
@@ -1141,7 +1141,6 @@ exit_remove:
                                   &(asc7621_params[i].sda.dev_attr));
        }
 
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return err;
 }
@@ -1196,7 +1195,6 @@ static int asc7621_remove(struct i2c_client *client)
                                   &(asc7621_params[i].sda.dev_attr));
        }
 
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return 0;
 }
index bad2cf3ef4a448aa76a72033b527647c6434f9d3..0f58ecc5334d941cb4114a3681e2e5a44893280e 100644 (file)
@@ -662,7 +662,6 @@ exit_remove:
        sysfs_remove_group(&client->dev.kobj, &f75375_group);
 exit_free:
        kfree(data);
-       i2c_set_clientdata(client, NULL);
        return err;
 }
 
@@ -672,7 +671,6 @@ static int f75375_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &f75375_group);
        kfree(data);
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index 09ea12e0a55185b3e5d0699cf7922898752b70af..1f63d1a3af5ebc4aae1d31f18d505881273b8a65 100644 (file)
@@ -236,7 +236,6 @@ error_hwmon_device_register:
        sysfs_remove_group(&client->dev.kobj, &g760a_group);
 error_sysfs_create_group:
        kfree(data);
-       i2c_set_clientdata(client, NULL);
 
        return err;
 }
@@ -247,7 +246,6 @@ static int g760a_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &g760a_group);
        kfree(data);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index e880e2c3871d0e2098913c7b130c3a35de7e4f65..937983407e2a47b12569d9ca4305af174e78f405 100644 (file)
@@ -289,6 +289,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
                        iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
                        iattr->s_attr.dev_attr.show = show_label;
                        iattr->s_attr.index = k;
+                       sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
                        res = device_create_file(&pdev->dev,
                                                 &iattr->s_attr.dev_attr);
                        if (res)
@@ -303,6 +304,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
                        iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
                        iattr->s_attr.dev_attr.show = show_amb_temp;
                        iattr->s_attr.index = k;
+                       sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
                        res = device_create_file(&pdev->dev,
                                                 &iattr->s_attr.dev_attr);
                        if (res)
@@ -318,6 +320,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
                        iattr->s_attr.dev_attr.show = show_amb_min;
                        iattr->s_attr.dev_attr.store = store_amb_min;
                        iattr->s_attr.index = k;
+                       sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
                        res = device_create_file(&pdev->dev,
                                                 &iattr->s_attr.dev_attr);
                        if (res)
@@ -333,6 +336,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
                        iattr->s_attr.dev_attr.show = show_amb_mid;
                        iattr->s_attr.dev_attr.store = store_amb_mid;
                        iattr->s_attr.index = k;
+                       sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
                        res = device_create_file(&pdev->dev,
                                                 &iattr->s_attr.dev_attr);
                        if (res)
@@ -348,6 +352,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
                        iattr->s_attr.dev_attr.show = show_amb_max;
                        iattr->s_attr.dev_attr.store = store_amb_max;
                        iattr->s_attr.index = k;
+                       sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
                        res = device_create_file(&pdev->dev,
                                                 &iattr->s_attr.dev_attr);
                        if (res)
@@ -362,6 +367,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
                        iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
                        iattr->s_attr.dev_attr.show = show_amb_alarm;
                        iattr->s_attr.index = k;
+                       sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
                        res = device_create_file(&pdev->dev,
                                                 &iattr->s_attr.dev_attr);
                        if (res)
index 099a2138cdf6ff739eda8826996a691b9f6ec0c0..da5a2404cd3eafe88584924ad82b7683e398502a 100644 (file)
@@ -112,11 +112,21 @@ static bool __devinit has_erratum_319(struct pci_dev *pdev)
        if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3)
                return false;
 
-       /* Differentiate between AM2+ (bad) and AM3 (good) */
+       /* DDR3 memory implies socket AM3, which is good */
        pci_bus_read_config_dword(pdev->bus,
                                  PCI_DEVFN(PCI_SLOT(pdev->devfn), 2),
                                  REG_DCT0_CONFIG_HIGH, &reg_dram_cfg);
-       return !(reg_dram_cfg & DDR3_MODE);
+       if (reg_dram_cfg & DDR3_MODE)
+               return false;
+
+       /*
+        * Unfortunately it is possible to run a socket AM3 CPU with DDR2
+        * memory. We blacklist all the cores which do exist in socket AM2+
+        * format. It still isn't perfect, as RB-C2 cores exist in both AM2+
+        * and AM3 formats, but that's the best we can do.
+        */
+       return boot_cpu_data.x86_model < 4 ||
+              (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2);
 }
 
 static int __devinit k10temp_probe(struct pci_dev *pdev,
index 0ceb6d6200a313b5e1ea5ef488f221ac929cdf80..f26acdb116819896c4e1e6bcb22eed2f364982ae 100644 (file)
@@ -120,7 +120,7 @@ static ssize_t show_temp(struct device *dev,
        int temp;
        struct k8temp_data *data = k8temp_update_device(dev);
 
-       if (data->swap_core_select)
+       if (data->swap_core_select && (data->sensorsp & SEL_CORE))
                core = core ? 0 : 1;
 
        temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset;
index 4d1b76bc81486b64dc6963d8ee415c2608c0fb82..29b9030d42c3111ecfdc49cc2a9cbf8aa4257cd6 100644 (file)
@@ -136,7 +136,6 @@ static int lm73_remove(struct i2c_client *client)
 
        hwmon_device_unregister(hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &lm73_group);
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index 56463428a419ce8f4222f5504b96f57cd44503fd..393f354f92a4c012c46ee96a8062f7b604697cdf 100644 (file)
@@ -192,7 +192,6 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
 exit_remove:
        sysfs_remove_group(&client->dev.kobj, &lm75_group);
 exit_free:
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return status;
 }
@@ -204,7 +203,6 @@ static int lm75_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &lm75_group);
        lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return 0;
 }
index 8fc8eb8cba47400fd23614a392b135949aab8c76..94741d42112da02ca902b2e87beacbe96aab3cd3 100644 (file)
@@ -399,7 +399,6 @@ static int lm95241_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &lm95241_group);
 
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return 0;
 }
index 8013895a1fafc19918faca9b838be7b4dc58d581..93187c3cb5e7949a72b5599bb127fce61701ec49 100644 (file)
@@ -224,7 +224,6 @@ fail_remove_sysfs:
 fail_restore_config:
        tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig);
 fail_free:
-       i2c_set_clientdata(client, NULL);
        kfree(tmp102);
 
        return status;
@@ -247,7 +246,6 @@ static int __devexit tmp102_remove(struct i2c_client *client)
                                         config | TMP102_CONF_SD);
        }
 
-       i2c_set_clientdata(client, NULL);
        kfree(tmp102);
 
        return 0;
index 738c472ece273bf972b1206e9b164b88d046b0bc..6b4165c12092b388c365824c49c8c7d6a65c9a8c 100644 (file)
@@ -295,7 +295,6 @@ exit_remove:
        sysfs_remove_group(&client->dev.kobj, &tmp421_group);
 
 exit_free:
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 
        return err;
@@ -308,7 +307,6 @@ static int tmp421_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &tmp421_group);
 
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 
        return 0;
index 32d4adee73db650fc5ba2b2cc42586b12b642cd3..c84b9b4e69609e70e55419a6faae4f8f1905a63c 100644 (file)
@@ -1197,7 +1197,6 @@ ERROR4:
        if (data->lm75[1])
                i2c_unregister_device(data->lm75[1]);
 ERROR3:
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 ERROR1:
        return err;
@@ -1219,7 +1218,6 @@ w83781d_remove(struct i2c_client *client)
        if (data->lm75[1])
                i2c_unregister_device(data->lm75[1]);
 
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 
        return 0;
index 87ab0568bb0ed1e18b979b675a5d8db0303ef545..bceafbfa72683698769890bfb664dbe57ea3a010 100644 (file)
@@ -475,6 +475,26 @@ config I2C_PASEMI
        help
          Supports the PA Semi PWRficient on-chip SMBus interfaces.
 
+config I2C_PCA_PLATFORM
+       tristate "PCA9564/PCA9665 as platform device"
+       select I2C_ALGOPCA
+       default n
+       help
+         This driver supports a memory mapped Philips PCA9564/PCA9665
+         parallel bus to I2C bus controller.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-pca-platform.
+
+config I2C_PMCMSP
+       tristate "PMC MSP I2C TWI Controller"
+       depends on PMC_MSP
+       help
+         This driver supports the PMC TWI controller on MSP devices.
+
+         This driver can also be built as module. If so, the module
+         will be called i2c-pmcmsp.
+
 config I2C_PNX
        tristate "I2C bus support for Philips PNX targets"
        depends on ARCH_PNX4008
@@ -711,26 +731,6 @@ config I2C_PCA_ISA
          delays when I2C/SMBus chip drivers are loaded (e.g. at boot
          time).  If unsure, say N.
 
-config I2C_PCA_PLATFORM
-       tristate "PCA9564/PCA9665 as platform device"
-       select I2C_ALGOPCA
-       default n
-       help
-         This driver supports a memory mapped Philips PCA9564/PCA9665
-         parallel bus to I2C bus controller.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-pca-platform.
-
-config I2C_PMCMSP
-       tristate "PMC MSP I2C TWI Controller"
-       depends on PMC_MSP
-       help
-         This driver supports the PMC TWI controller on MSP devices.
-
-         This driver can also be built as module. If so, the module
-         will be called i2c-pmcmsp.
-
 config I2C_SIBYTE
        tristate "SiByte SMBus interface"
        depends on SIBYTE_SB1xxx_SOC
index 097236f631e8d68e57a2ca87562912c995f280ca..936880bd1dc58404d4ed666919939729c7c99585 100644 (file)
@@ -27,7 +27,7 @@ obj-$(CONFIG_I2C_VIAPRO)      += i2c-viapro.o
 obj-$(CONFIG_I2C_HYDRA)                += i2c-hydra.o
 obj-$(CONFIG_I2C_POWERMAC)     += i2c-powermac.o
 
-# Embebbed system I2C/SMBus host controller drivers
+# Embedded system I2C/SMBus host controller drivers
 obj-$(CONFIG_I2C_AT91)         += i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)       += i2c-au1550.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
@@ -46,6 +46,8 @@ obj-$(CONFIG_I2C_NOMADIK)     += i2c-nomadik.o
 obj-$(CONFIG_I2C_OCORES)       += i2c-ocores.o
 obj-$(CONFIG_I2C_OMAP)         += i2c-omap.o
 obj-$(CONFIG_I2C_PASEMI)       += i2c-pasemi.o
+obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
+obj-$(CONFIG_I2C_PMCMSP)       += i2c-pmcmsp.o
 obj-$(CONFIG_I2C_PNX)          += i2c-pnx.o
 obj-$(CONFIG_I2C_PXA)          += i2c-pxa.o
 obj-$(CONFIG_I2C_S3C2410)      += i2c-s3c2410.o
@@ -68,8 +70,6 @@ obj-$(CONFIG_I2C_TINY_USB)    += i2c-tiny-usb.o
 obj-$(CONFIG_I2C_ACORN)                += i2c-acorn.o
 obj-$(CONFIG_I2C_ELEKTOR)      += i2c-elektor.o
 obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
-obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
-obj-$(CONFIG_I2C_PMCMSP)       += i2c-pmcmsp.o
 obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
 obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
index e0f833cca3f1193c24480c4efc446a7568a9a3af..1cca2631e5b3bc8331062617a68968006a9fd06e 100644 (file)
@@ -47,7 +47,6 @@ static DEFINE_MUTEX(core_lock);
 static DEFINE_IDR(i2c_adapter_idr);
 
 static struct device_type i2c_client_type;
-static int i2c_check_addr(struct i2c_adapter *adapter, int addr);
 static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
 
 /* ------------------------------------------------------------------------- */
@@ -371,6 +370,59 @@ struct i2c_client *i2c_verify_client(struct device *dev)
 EXPORT_SYMBOL(i2c_verify_client);
 
 
+/* This is a permissive address validity check, I2C address map constraints
+ * are purposedly not enforced, except for the general call address. */
+static int i2c_check_client_addr_validity(const struct i2c_client *client)
+{
+       if (client->flags & I2C_CLIENT_TEN) {
+               /* 10-bit address, all values are valid */
+               if (client->addr > 0x3ff)
+                       return -EINVAL;
+       } else {
+               /* 7-bit address, reject the general call address */
+               if (client->addr == 0x00 || client->addr > 0x7f)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+/* And this is a strict address validity check, used when probing. If a
+ * device uses a reserved address, then it shouldn't be probed. 7-bit
+ * addressing is assumed, 10-bit address devices are rare and should be
+ * explicitly enumerated. */
+static int i2c_check_addr_validity(unsigned short addr)
+{
+       /*
+        * Reserved addresses per I2C specification:
+        *  0x00       General call address / START byte
+        *  0x01       CBUS address
+        *  0x02       Reserved for different bus format
+        *  0x03       Reserved for future purposes
+        *  0x04-0x07  Hs-mode master code
+        *  0x78-0x7b  10-bit slave addressing
+        *  0x7c-0x7f  Reserved for future purposes
+        */
+       if (addr < 0x08 || addr > 0x77)
+               return -EINVAL;
+       return 0;
+}
+
+static int __i2c_check_addr_busy(struct device *dev, void *addrp)
+{
+       struct i2c_client       *client = i2c_verify_client(dev);
+       int                     addr = *(int *)addrp;
+
+       if (client && client->addr == addr)
+               return -EBUSY;
+       return 0;
+}
+
+static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr)
+{
+       return device_for_each_child(&adapter->dev, &addr,
+                                    __i2c_check_addr_busy);
+}
+
 /**
  * i2c_new_device - instantiate an i2c device
  * @adap: the adapter managing the device
@@ -410,8 +462,16 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
 
        strlcpy(client->name, info->type, sizeof(client->name));
 
+       /* Check for address validity */
+       status = i2c_check_client_addr_validity(client);
+       if (status) {
+               dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",
+                       client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);
+               goto out_err_silent;
+       }
+
        /* Check for address business */
-       status = i2c_check_addr(adap, client->addr);
+       status = i2c_check_addr_busy(adap, client->addr);
        if (status)
                goto out_err;
 
@@ -436,6 +496,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
 out_err:
        dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "
                "(%d)\n", client->name, client->addr, status);
+out_err_silent:
        kfree(client);
        return NULL;
 }
@@ -561,15 +622,9 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
        }
 
-       if (info.addr < 0x03 || info.addr > 0x77) {
-               dev_err(dev, "%s: Invalid I2C address 0x%hx\n", "new_device",
-                       info.addr);
-               return -EINVAL;
-       }
-
        client = i2c_new_device(adap, &info);
        if (!client)
-               return -EEXIST;
+               return -EINVAL;
 
        /* Keep track of the added device */
        i2c_lock_adapter(adap);
@@ -1024,21 +1079,6 @@ EXPORT_SYMBOL(i2c_del_driver);
 
 /* ------------------------------------------------------------------------- */
 
-static int __i2c_check_addr(struct device *dev, void *addrp)
-{
-       struct i2c_client       *client = i2c_verify_client(dev);
-       int                     addr = *(int *)addrp;
-
-       if (client && client->addr == addr)
-               return -EBUSY;
-       return 0;
-}
-
-static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
-{
-       return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr);
-}
-
 /**
  * i2c_use_client - increments the reference count of the i2c client structure
  * @client: the client being referenced
@@ -1277,6 +1317,41 @@ EXPORT_SYMBOL(i2c_master_recv);
  * ----------------------------------------------------
  */
 
+/*
+ * Legacy default probe function, mostly relevant for SMBus. The default
+ * probe method is a quick write, but it is known to corrupt the 24RF08
+ * EEPROMs due to a state machine bug, and could also irreversibly
+ * write-protect some EEPROMs, so for address ranges 0x30-0x37 and 0x50-0x5f,
+ * we use a short byte read instead. Also, some bus drivers don't implement
+ * quick write, so we fallback to a byte read in that case too.
+ * On x86, there is another special case for FSC hardware monitoring chips,
+ * which want regular byte reads (address 0x73.) Fortunately, these are the
+ * only known chips using this I2C address on PC hardware.
+ * Returns 1 if probe succeeded, 0 if not.
+ */
+static int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr)
+{
+       int err;
+       union i2c_smbus_data dummy;
+
+#ifdef CONFIG_X86
+       if (addr == 0x73 && (adap->class & I2C_CLASS_HWMON)
+        && i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE_DATA))
+               err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,
+                                    I2C_SMBUS_BYTE_DATA, &dummy);
+       else
+#endif
+       if ((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50
+        || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK))
+               err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,
+                                    I2C_SMBUS_BYTE, &dummy);
+       else
+               err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0,
+                                    I2C_SMBUS_QUICK, NULL);
+
+       return err >= 0;
+}
+
 static int i2c_detect_address(struct i2c_client *temp_client,
                              struct i2c_driver *driver)
 {
@@ -1286,34 +1361,20 @@ static int i2c_detect_address(struct i2c_client *temp_client,
        int err;
 
        /* Make sure the address is valid */
-       if (addr < 0x03 || addr > 0x77) {
+       err = i2c_check_addr_validity(addr);
+       if (err) {
                dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
                         addr);
-               return -EINVAL;
+               return err;
        }
 
        /* Skip if already in use */
-       if (i2c_check_addr(adapter, addr))
+       if (i2c_check_addr_busy(adapter, addr))
                return 0;
 
        /* Make sure there is something at this address */
-       if (addr == 0x73 && (adapter->class & I2C_CLASS_HWMON)) {
-               /* Special probe for FSC hwmon chips */
-               union i2c_smbus_data dummy;
-
-               if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0,
-                                  I2C_SMBUS_BYTE_DATA, &dummy) < 0)
-                       return 0;
-       } else {
-               if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0,
-                                  I2C_SMBUS_QUICK, NULL) < 0)
-                       return 0;
-
-               /* Prevent 24RF08 corruption */
-               if ((addr & ~0x0f) == 0x50)
-                       i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0,
-                                      I2C_SMBUS_QUICK, NULL);
-       }
+       if (!i2c_default_probe(adapter, addr))
+               return 0;
 
        /* Finally call the custom detection function */
        memset(&info, 0, sizeof(struct i2c_board_info));
@@ -1407,42 +1468,22 @@ i2c_new_probed_device(struct i2c_adapter *adap,
 
        for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
                /* Check address validity */
-               if (addr_list[i] < 0x03 || addr_list[i] > 0x77) {
+               if (i2c_check_addr_validity(addr_list[i]) < 0) {
                        dev_warn(&adap->dev, "Invalid 7-bit address "
                                 "0x%02x\n", addr_list[i]);
                        continue;
                }
 
                /* Check address availability */
-               if (i2c_check_addr(adap, addr_list[i])) {
+               if (i2c_check_addr_busy(adap, addr_list[i])) {
                        dev_dbg(&adap->dev, "Address 0x%02x already in "
                                "use, not probing\n", addr_list[i]);
                        continue;
                }
 
-               /* Test address responsiveness
-                  The default probe method is a quick write, but it is known
-                  to corrupt the 24RF08 EEPROMs due to a state machine bug,
-                  and could also irreversibly write-protect some EEPROMs, so
-                  for address ranges 0x30-0x37 and 0x50-0x5f, we use a byte
-                  read instead. Also, some bus drivers don't implement
-                  quick write, so we fallback to a byte read it that case
-                  too. */
-               if ((addr_list[i] & ~0x07) == 0x30
-                || (addr_list[i] & ~0x0f) == 0x50
-                || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) {
-                       union i2c_smbus_data data;
-
-                       if (i2c_smbus_xfer(adap, addr_list[i], 0,
-                                          I2C_SMBUS_READ, 0,
-                                          I2C_SMBUS_BYTE, &data) >= 0)
-                               break;
-               } else {
-                       if (i2c_smbus_xfer(adap, addr_list[i], 0,
-                                          I2C_SMBUS_WRITE, 0,
-                                          I2C_SMBUS_QUICK, NULL) >= 0)
-                               break;
-               }
+               /* Test address responsiveness */
+               if (i2c_default_probe(adap, addr_list[i]))
+                       break;
        }
 
        if (addr_list[i] == I2C_CLIENT_END) {
index a24e0bfe9201a87a7012b1f42791d925aaf5b76f..f61ccc1e5ea3ea7a350af1cc3ec7858bf0f5dbe8 100644 (file)
@@ -173,7 +173,6 @@ static int smbalert_remove(struct i2c_client *ara)
 
        cancel_work_sync(&alert->alert);
 
-       i2c_set_clientdata(ara, NULL);
        kfree(alert);
        return 0;
 }
index 183fa38760d85be4e520529c0747b6d88a614365..ebcf8e470a97b2685a1bf9b63b2e16c7a0b3b581 100644 (file)
@@ -1400,8 +1400,11 @@ static struct of_device_id pmac_ide_macio_match[] =
 
 static struct macio_driver pmac_ide_macio_driver = 
 {
-       .name           = "ide-pmac",
-       .match_table    = pmac_ide_macio_match,
+       .driver = {
+               .name           = "ide-pmac",
+               .owner          = THIS_MODULE,
+               .of_match_table = pmac_ide_macio_match,
+       },
        .probe          = pmac_ide_macio_attach,
        .suspend        = pmac_ide_macio_suspend,
        .resume         = pmac_ide_macio_resume,
index edef8527eb34899a85c4b61fd33605e240bda49c..844954bf417b7cc10fd13a3c103388b4099e8f79 100644 (file)
@@ -542,10 +542,8 @@ static int qibfs_fill_super(struct super_block *sb, void *data, int silent)
        list_for_each_entry_safe(dd, tmp, &qib_dev_list, list) {
                spin_unlock_irqrestore(&qib_devs_lock, flags);
                ret = add_cntr_files(sb, dd);
-               if (ret) {
-                       deactivate_super(sb);
+               if (ret)
                        goto bail;
-               }
                spin_lock_irqsave(&qib_devs_lock, flags);
        }
 
index d8fa5d724c572ebc6c9eb77e3f8cb2dda548cbd3..0f9a4785d7980feca1cc65d5b7504906535ea5f2 100644 (file)
@@ -69,7 +69,7 @@ config KEYBOARD_ATARI
          module will be called atakbd.
 
 config KEYBOARD_ATKBD
-       tristate "AT keyboard" if EMBEDDED || !X86
+       tristate "AT keyboard" if EMBEDDED || !X86 || X86_MRST
        default y
        select SERIO
        select SERIO_LIBPS2
index 4771ab172b59b22dda93eaa5437aba8019d7a208..744600eff222935b8af076ac8122c07f22a896e9 100644 (file)
@@ -287,7 +287,6 @@ static int __devexit adp5588_remove(struct i2c_client *client)
        free_irq(client->irq, kpad);
        cancel_delayed_work_sync(&kpad->work);
        input_unregister_device(kpad->input);
-       i2c_set_clientdata(client, NULL);
        kfree(kpad);
 
        return 0;
index bc696931fed7b127a87afb262f63aa26fc63ac9a..40b032f0e32cd47a12e33f300810da9a131941c0 100644 (file)
@@ -778,8 +778,6 @@ static int __devexit lm8323_remove(struct i2c_client *client)
        struct lm8323_chip *lm = i2c_get_clientdata(client);
        int i;
 
-       i2c_set_clientdata(client, NULL);
-
        disable_irq_wake(client->irq);
        free_irq(client->irq, lm);
        cancel_work_sync(&lm->work);
index 7fc8185e5c1bd8ab914cedb0f0d78e15e974ed89..9091ff5ea808b8829d7d9475f15f704532d10c5e 100644 (file)
@@ -265,7 +265,6 @@ static int __devexit max7359_remove(struct i2c_client *client)
 
        free_irq(client->irq, keypad);
        input_unregister_device(keypad->input_dev);
-       i2c_set_clientdata(client, NULL);
        kfree(keypad);
 
        return 0;
index 31f30087b591866c9e81af4401d0a3feeaae359e..fac695157e8afce221fb8dae22fa2d750d745963 100644 (file)
@@ -358,7 +358,6 @@ static int __devexit qt2160_remove(struct i2c_client *client)
        input_unregister_device(qt2160->input);
        kfree(qt2160);
 
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index 493c93f25e2abb96c0555d46d6ac9f20801d9098..00137bebcf974a8133ff3f4f4234bcace30cd084 100644 (file)
@@ -316,8 +316,6 @@ static int __devexit tca6416_keypad_remove(struct i2c_client *client)
        input_unregister_device(chip->input);
        kfree(chip);
 
-       i2c_set_clientdata(client, NULL);
-
        return 0;
 }
 
index e9adbe49f6a49fe0a01e74648747985cb517061d..2bef8fa56c948e0ba4305ea0f4f22450244f79d4 100644 (file)
@@ -97,7 +97,6 @@ static int __devexit ad714x_i2c_remove(struct i2c_client *client)
        struct ad714x_chip *chip = i2c_get_clientdata(client);
 
        ad714x_remove(chip);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index e00a1cc79c0a448d5b344612ee9c7354b86c342c..c19066479057ff3567d7168c38922e0fd0b84da3 100644 (file)
@@ -678,7 +678,7 @@ static const struct file_operations hp_sdc_rtc_fops = {
         .llseek =              no_llseek,
         .read =                        hp_sdc_rtc_read,
         .poll =                        hp_sdc_rtc_poll,
-        .unlocked_ioctl =      hp_sdc_rtc_ioctl,
+        .unlocked_ioctl =      hp_sdc_rtc_unlocked_ioctl,
         .open =                        hp_sdc_rtc_open,
         .fasync =              hp_sdc_rtc_fasync,
 };
index 5c3ac4e0b055837976624cbd3ef1873cc81d82c6..4b42ffc0532af1c6a3b36ca64ab411decfac89d9 100644 (file)
@@ -69,7 +69,7 @@ static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id)
        unsigned char nextstate = read_state(lp);
 
        if (lp->laststate != nextstate) {
-               int key_down = nextstate <= ARRAY_SIZE(lp->btncode);
+               int key_down = nextstate < ARRAY_SIZE(lp->btncode);
                unsigned short keycode = key_down ?
                        lp->btncode[nextstate] : lp->btncode[lp->laststate];
 
@@ -168,8 +168,6 @@ static int __devexit pcf8574_kp_remove(struct i2c_client *client)
        input_unregister_device(lp->idev);
        kfree(lp);
 
-       i2c_set_clientdata(client, NULL);
-
        return 0;
 }
 
index 8291e7399ffab3606d2563a8e7257e513b5179f6..0ae62f0bcb3216ca32c494e3a807a75a8f6753bd 100644 (file)
@@ -613,7 +613,6 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client)
                free_irq(client->irq, touch);
 
        input_unregister_device(touch->input);
-       i2c_set_clientdata(client, NULL);
        kfree(touch);
 
        return 0;
index f34f1dbeb5773aa1810509e45d05b2e2a543c4fb..256b9e9394dc805b2062f1e70f3f7abd24814647 100644 (file)
@@ -21,7 +21,8 @@ if SERIO
 config SERIO_I8042
        tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
        default y
-       depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BLACKFIN
+       depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
+                  (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !X86_MRST
        help
          i8042 is the chip over which the standard AT keyboard and PS/2
          mouse are connected to the computer. If you use these devices,
index 2dc0c07c04699de92a3a101b1a6f78cf45d7cc48..42ba3691d908bc1fc8c370da5ada4287ceb21115 100644 (file)
@@ -507,7 +507,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
                        goto fail3;
        }
 
-       input_dev->name = wacom_wac->name;
        input_dev->name = wacom_wac->name;
        input_dev->dev.parent = &intf->dev;
        input_dev->open = wacom_open;
index 847fd0135bcf92b547a5303ad528c563bf5fe903..415f6306105dba7ae722e3c5ce5706fb09109949 100644 (file)
@@ -284,12 +284,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                        (data[4] << 20) + (data[5] << 12) +
                        (data[6] << 4) + (data[7] >> 4);
 
-               wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);
+               wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
+                       ((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
 
-               switch (wacom->id[idx]) {
+               switch (wacom->id[idx] & 0xfffff) {
                case 0x812: /* Inking pen */
                case 0x801: /* Intuos3 Inking pen */
-               case 0x20802: /* Intuos4 Classic Pen */
+               case 0x20802: /* Intuos4 Inking Pen */
                case 0x012:
                        wacom->tool[idx] = BTN_TOOL_PENCIL;
                        break;
@@ -300,7 +301,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                case 0x823: /* Intuos3 Grip Pen */
                case 0x813: /* Intuos3 Classic Pen */
                case 0x885: /* Intuos3 Marker Pen */
-               case 0x802: /* Intuos4 Grip Pen Eraser */
+               case 0x802: /* Intuos4 General Pen */
                case 0x804: /* Intuos4 Marker Pen */
                case 0x40802: /* Intuos4 Classic Pen */
                case 0x022:
@@ -335,7 +336,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                case 0x81b: /* Intuos3 Classic Pen Eraser */
                case 0x91b: /* Intuos3 Airbrush Eraser */
                case 0x80c: /* Intuos4 Marker Pen Eraser */
-               case 0x80a: /* Intuos4 Grip Pen Eraser */
+               case 0x80a: /* Intuos4 General Pen Eraser */
                case 0x4080a: /* Intuos4 Classic Pen Eraser */
                case 0x90a: /* Intuos4 Airbrush Eraser */
                        wacom->tool[idx] = BTN_TOOL_RUBBER;
@@ -356,6 +357,11 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                return 1;
        }
 
+       /* older I4 styli don't work with new Cintiqs */
+       if (!((wacom->id[idx] >> 20) & 0x01) &&
+                       (features->type == WACOM_21UX2))
+               return 1;
+
        /* Exit report */
        if ((data[1] & 0xfe) == 0x80) {
                /*
@@ -474,21 +480,43 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                                input_report_abs(input, ABS_MISC, 0);
                        }
                } else {
-                       input_report_key(input, BTN_0, (data[5] & 0x01));
-                       input_report_key(input, BTN_1, (data[5] & 0x02));
-                       input_report_key(input, BTN_2, (data[5] & 0x04));
-                       input_report_key(input, BTN_3, (data[5] & 0x08));
-                       input_report_key(input, BTN_4, (data[6] & 0x01));
-                       input_report_key(input, BTN_5, (data[6] & 0x02));
-                       input_report_key(input, BTN_6, (data[6] & 0x04));
-                       input_report_key(input, BTN_7, (data[6] & 0x08));
-                       input_report_key(input, BTN_8, (data[5] & 0x10));
-                       input_report_key(input, BTN_9, (data[6] & 0x10));
+                       if (features->type == WACOM_21UX2) {
+                               input_report_key(input, BTN_0, (data[5] & 0x01));
+                               input_report_key(input, BTN_1, (data[6] & 0x01));
+                               input_report_key(input, BTN_2, (data[6] & 0x02));
+                               input_report_key(input, BTN_3, (data[6] & 0x04));
+                               input_report_key(input, BTN_4, (data[6] & 0x08));
+                               input_report_key(input, BTN_5, (data[6] & 0x10));
+                               input_report_key(input, BTN_6, (data[6] & 0x20));
+                               input_report_key(input, BTN_7, (data[6] & 0x40));
+                               input_report_key(input, BTN_8, (data[6] & 0x80));
+                               input_report_key(input, BTN_9, (data[7] & 0x01));
+                               input_report_key(input, BTN_A, (data[8] & 0x01));
+                               input_report_key(input, BTN_B, (data[8] & 0x02));
+                               input_report_key(input, BTN_C, (data[8] & 0x04));
+                               input_report_key(input, BTN_X, (data[8] & 0x08));
+                               input_report_key(input, BTN_Y, (data[8] & 0x10));
+                               input_report_key(input, BTN_Z, (data[8] & 0x20));
+                               input_report_key(input, BTN_BASE, (data[8] & 0x40));
+                               input_report_key(input, BTN_BASE2, (data[8] & 0x80));
+                       } else {
+                               input_report_key(input, BTN_0, (data[5] & 0x01));
+                               input_report_key(input, BTN_1, (data[5] & 0x02));
+                               input_report_key(input, BTN_2, (data[5] & 0x04));
+                               input_report_key(input, BTN_3, (data[5] & 0x08));
+                               input_report_key(input, BTN_4, (data[6] & 0x01));
+                               input_report_key(input, BTN_5, (data[6] & 0x02));
+                               input_report_key(input, BTN_6, (data[6] & 0x04));
+                               input_report_key(input, BTN_7, (data[6] & 0x08));
+                               input_report_key(input, BTN_8, (data[5] & 0x10));
+                               input_report_key(input, BTN_9, (data[6] & 0x10));
+                       }
                        input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
                        input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
 
-                       if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
-                               data[2] | (data[3] & 0x1f) | data[4]) {
+                       if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
+                               data[2] | (data[3] & 0x1f) | data[4] | data[8] |
+                               (data[7] & 0x01)) {
                                input_report_key(input, wacom->tool[1], 1);
                                input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
                        } else {
@@ -640,7 +668,7 @@ static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx)
        if (!idx)
                input_report_key(input, BTN_TOUCH, 1);
        input_event(input, EV_MSC, MSC_SERIAL, finger);
-       input_sync(wacom->input);
+       input_sync(input);
 
        wacom->last_finger = finger;
 }
@@ -826,6 +854,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
        case INTUOS4L:
        case CINTIQ:
        case WACOM_BEE:
+       case WACOM_21UX2:
                sync = wacom_intuos_irq(wacom_wac);
                break;
 
@@ -921,6 +950,17 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
                __set_bit(BTN_STYLUS2, input_dev->keybit);
                break;
 
+       case WACOM_21UX2:
+               __set_bit(BTN_A, input_dev->keybit);
+               __set_bit(BTN_B, input_dev->keybit);
+               __set_bit(BTN_C, input_dev->keybit);
+               __set_bit(BTN_X, input_dev->keybit);
+               __set_bit(BTN_Y, input_dev->keybit);
+               __set_bit(BTN_Z, input_dev->keybit);
+               __set_bit(BTN_BASE, input_dev->keybit);
+               __set_bit(BTN_BASE2, input_dev->keybit);
+               /* fall through */
+
        case WACOM_BEE:
                __set_bit(BTN_8, input_dev->keybit);
                __set_bit(BTN_9, input_dev->keybit);
@@ -1105,6 +1145,8 @@ static const struct wacom_features wacom_features_0xBA =
        { "Wacom Intuos4 8x13",   WACOM_PKGLEN_INTUOS,    65024, 40640, 2047, 63, INTUOS4L };
 static const struct wacom_features wacom_features_0xBB =
        { "Wacom Intuos4 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 2047, 63, INTUOS4L };
+static const struct wacom_features wacom_features_0xBC =
+       { "Wacom Intuos4 WL",     WACOM_PKGLEN_INTUOS,    40840, 25400, 2047, 63, INTUOS4 };
 static const struct wacom_features wacom_features_0x3F =
        { "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023, 63, CINTIQ };
 static const struct wacom_features wacom_features_0xC5 =
@@ -1113,6 +1155,8 @@ static const struct wacom_features wacom_features_0xC6 =
        { "Wacom Cintiq 12WX",    WACOM_PKGLEN_INTUOS,    53020, 33440, 1023, 63, WACOM_BEE };
 static const struct wacom_features wacom_features_0xC7 =
        { "Wacom DTU1931",        WACOM_PKGLEN_GRAPHIRE,  37832, 30305,  511,  0, PL };
+static const struct wacom_features wacom_features_0xCC =
+       { "Wacom Cintiq 21UX2",   WACOM_PKGLEN_INTUOS,    87200, 65600, 2047, 63, WACOM_21UX2 };
 static const struct wacom_features wacom_features_0x90 =
        { "Wacom ISDv4 90",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC };
 static const struct wacom_features wacom_features_0x93 =
@@ -1185,10 +1229,12 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xB9) },
        { USB_DEVICE_WACOM(0xBA) },
        { USB_DEVICE_WACOM(0xBB) },
+       { USB_DEVICE_WACOM(0xBC) },
        { USB_DEVICE_WACOM(0x3F) },
        { USB_DEVICE_WACOM(0xC5) },
        { USB_DEVICE_WACOM(0xC6) },
        { USB_DEVICE_WACOM(0xC7) },
+       { USB_DEVICE_WACOM(0xCC) },
        { USB_DEVICE_WACOM(0x90) },
        { USB_DEVICE_WACOM(0x93) },
        { USB_DEVICE_WACOM(0x9A) },
index 063f1af3204fb5dab3b2c8d85e47a56a54395727..854b92092dfcb8663f29bf601adc62d40ce71d1d 100644 (file)
@@ -50,6 +50,7 @@ enum {
        INTUOS4S,
        INTUOS4,
        INTUOS4L,
+       WACOM_21UX2,
        CINTIQ,
        WACOM_BEE,
        WACOM_MO,
index 6703c6b9800a4c290fde19dc5f1ab10c4ed2dc1f..3b9d5e2105d76d9fbfdd1a8d4cab9bf80f411b25 100644 (file)
@@ -156,7 +156,7 @@ config TOUCHSCREEN_FUJITSU
 config TOUCHSCREEN_S3C2410
        tristate "Samsung S3C2410/generic touchscreen input driver"
        depends on ARCH_S3C2410 || SAMSUNG_DEV_TS
-       select S3C24XX_ADC
+       select S3C_ADC
        help
          Say Y here if you have the s3c2410 touchscreen.
 
index 0d2d7e54b465a2d06d63e777acb260f4698f0239..5f0221cffef9bf12821ed9fd38d63bac0df720dc 100644 (file)
@@ -679,6 +679,13 @@ static int __devinit ad7877_probe(struct spi_device *spi)
                return -EINVAL;
        }
 
+       spi->bits_per_word = 16;
+       err = spi_setup(spi);
+       if (err) {
+               dev_dbg(&spi->dev, "spi master doesn't support 16 bits/word\n");
+               return err;
+       }
+
        ts = kzalloc(sizeof(struct ad7877), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!ts || !input_dev) {
index 794d070c6900607752f2af1b7641f0cc98ef267f..4b32fb4704cd37b24f67c84db53de4ed431320c8 100644 (file)
@@ -812,10 +812,8 @@ static int __devinit ad7879_probe(struct i2c_client *client,
        ts->bus = client;
 
        error = ad7879_construct(client, ts);
-       if (error) {
-               i2c_set_clientdata(client, NULL);
+       if (error)
                kfree(ts);
-       }
 
        return error;
 }
@@ -825,7 +823,6 @@ static int __devexit ad7879_remove(struct i2c_client *client)
        struct ad7879 *ts = dev_get_drvdata(&client->dev);
 
        ad7879_destroy(client, ts);
-       i2c_set_clientdata(client, NULL);
        kfree(ts);
 
        return 0;
index 634f6f6b9b1349a27bcca9a056ca27a1b5151abc..a9fdf55c0238b14b4c6fa54fa257002f925d3daa 100644 (file)
@@ -1164,7 +1164,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
        ts->reg = regulator_get(&spi->dev, "vcc");
        if (IS_ERR(ts->reg)) {
                err = PTR_ERR(ts->reg);
-               dev_err(&spi->dev, "unable to get regulator: %ld\n", err);
+               dev_err(&spi->dev, "unable to get regulator: %d\n", err);
                goto err_free_gpio;
        }
 
index 75f8b73010fa5aa30dd3758a7421697b16c03e46..7a3a916f84a857137332ba89a53373d9dfe136d7 100644 (file)
@@ -238,7 +238,6 @@ err2:
        input = NULL; /* so we dont try to free it below */
 err1:
        input_free_device(input);
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
 err0:
        return err;
@@ -256,7 +255,6 @@ static int __devexit eeti_ts_remove(struct i2c_client *client)
        enable_irq(priv->irq);
 
        input_unregister_device(priv->input);
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
 
        return 0;
index ce8ab0269f6fc755f6496e90a5a4cd4c8157b816..1fb0c2f06a4470657b1b05e5295b77b3c67d6236 100644 (file)
@@ -256,7 +256,6 @@ static int __devexit mcs5000_ts_remove(struct i2c_client *client)
        free_irq(client->irq, data);
        input_unregister_device(data->input_dev);
        kfree(data);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index ac5d0f9b0cb14bac59636f3ae01315a517070567..6085d12fd56196e0e47873bade9b4880ab5ca356 100644 (file)
@@ -173,7 +173,7 @@ static irqreturn_t stylus_irq(int irq, void *dev_id)
        if (down)
                s3c_adc_start(ts.client, 0, 1 << ts.shift);
        else
-               dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count);
+               dev_dbg(ts.dev, "%s: count=%d\n", __func__, ts.count);
 
        if (ts.features & FEAT_PEN_IRQ) {
                /* Clear pen down/up interrupt */
index 5de80a1a730b79ef129bf3f6980878719c04417a..5b70a1419b4d6da36fe5486b5b732d647691bdff 100644 (file)
@@ -221,7 +221,7 @@ done:
 
        if (poll) {
                schd = queue_delayed_work(tsc->wq, &tsc->work,
-                                         tsc->poll_period * HZ / 1000);
+                                         msecs_to_jiffies(tsc->poll_period));
                if (schd)
                        tsc->polling = 1;
                else {
@@ -326,7 +326,7 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
                goto err2;
 
        schd = queue_delayed_work(tsc->wq, &tsc->work,
-                                 tsc->poll_period * HZ / 1000);
+                                 msecs_to_jiffies(tsc->poll_period));
 
        if (schd)
                tsc->polling = 1;
@@ -339,10 +339,8 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
        return 0;
 
 err2:
-       cancel_delayed_work(&tsc->work);
-       flush_workqueue(tsc->wq);
+       cancel_delayed_work_sync(&tsc->work);
        destroy_workqueue(tsc->wq);
-       tsc->wq = 0;
        input_free_device(input_dev);
 err1:
        kfree(tsc);
@@ -360,10 +358,8 @@ static int __devexit tps6507x_ts_remove(struct platform_device *pdev)
        if (!tsc)
                return 0;
 
-       cancel_delayed_work(&tsc->work);
-       flush_workqueue(tsc->wq);
+       cancel_delayed_work_sync(&tsc->work);
        destroy_workqueue(tsc->wq);
-       tsc->wq = 0;
 
        input_free_device(input_dev);
 
index 769b479fcaa625fb4406096dd84746b89cc877e4..be23780e8a3e3b81be9df7b7cd0f8aab86d87e61 100644 (file)
@@ -347,8 +347,6 @@ static int __devexit tsc2007_remove(struct i2c_client *client)
        struct tsc2007  *ts = i2c_get_clientdata(client);
        struct tsc2007_platform_data *pdata = client->dev.platform_data;
 
-       i2c_set_clientdata(client, NULL);
-
        tsc2007_free_irq(ts);
 
        if (pdata->exit_platform_hw)
index bde3c88b8b270e0ca527849b0f58c9647bfb67ad..b054494df846958d99fdc45c4075dc57339981bd 100644 (file)
@@ -1020,12 +1020,12 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
                if (cmd == AVMB1_ADDCARD) {
                   if ((retval = copy_from_user(&cdef, data,
                                            sizeof(avmb1_carddef))))
-                          return retval;
+                          return -EFAULT;
                   cdef.cardtype = AVM_CARDTYPE_B1;
                } else {
                   if ((retval = copy_from_user(&cdef, data,
                                            sizeof(avmb1_extcarddef))))
-                          return retval;
+                          return -EFAULT;
                }
                cparams.port = cdef.port;
                cparams.irq = cdef.irq;
@@ -1218,7 +1218,7 @@ int capi20_manufacturer(unsigned int cmd, void __user *data)
                kcapi_carddef cdef;
 
                if ((retval = copy_from_user(&cdef, data, sizeof(cdef))))
-                       return retval;
+                       return -EFAULT;
 
                cparams.port = cdef.port;
                cparams.irq = cdef.irq;
index c5016bd2d94f6d10f132a288e3b9b11e5185b66f..c3b1dc3a13a0f998a23e01b81d3b99ede2bc2428 100644 (file)
@@ -126,26 +126,6 @@ static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf)
        return numbytes;
 }
 
-/* set up next receive skb for data mode
- */
-static void new_rcv_skb(struct bc_state *bcs)
-{
-       struct cardstate *cs = bcs->cs;
-       unsigned short hw_hdr_len = cs->hw_hdr_len;
-
-       if (bcs->ignore) {
-               bcs->skb = NULL;
-               return;
-       }
-
-       bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len);
-       if (bcs->skb == NULL) {
-               dev_warn(cs->dev, "could not allocate new skb\n");
-               return;
-       }
-       skb_reserve(bcs->skb, hw_hdr_len);
-}
-
 /* process a block of received bytes in HDLC data mode
  * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC)
  * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
@@ -159,8 +139,8 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
        struct cardstate *cs = inbuf->cs;
        struct bc_state *bcs = cs->bcs;
        int inputstate = bcs->inputstate;
-       __u16 fcs = bcs->fcs;
-       struct sk_buff *skb = bcs->skb;
+       __u16 fcs = bcs->rx_fcs;
+       struct sk_buff *skb = bcs->rx_skb;
        unsigned char *src = inbuf->data + inbuf->head;
        unsigned procbytes = 0;
        unsigned char c;
@@ -245,8 +225,7 @@ byte_stuff:
 
                                /* prepare reception of next frame */
                                inputstate &= ~INS_have_data;
-                               new_rcv_skb(bcs);
-                               skb = bcs->skb;
+                               skb = gigaset_new_rx_skb(bcs);
                        } else {
                                /* empty frame (7E 7E) */
 #ifdef CONFIG_GIGASET_DEBUG
@@ -255,8 +234,7 @@ byte_stuff:
                                if (!skb) {
                                        /* skipped (?) */
                                        gigaset_isdn_rcv_err(bcs);
-                                       new_rcv_skb(bcs);
-                                       skb = bcs->skb;
+                                       skb = gigaset_new_rx_skb(bcs);
                                }
                        }
 
@@ -279,11 +257,11 @@ byte_stuff:
 #endif
                inputstate |= INS_have_data;
                if (skb) {
-                       if (skb->len == SBUFSIZE) {
+                       if (skb->len >= bcs->rx_bufsize) {
                                dev_warn(cs->dev, "received packet too long\n");
                                dev_kfree_skb_any(skb);
                                /* skip remainder of packet */
-                               bcs->skb = skb = NULL;
+                               bcs->rx_skb = skb = NULL;
                        } else {
                                *__skb_put(skb, 1) = c;
                                fcs = crc_ccitt_byte(fcs, c);
@@ -292,7 +270,7 @@ byte_stuff:
        }
 
        bcs->inputstate = inputstate;
-       bcs->fcs = fcs;
+       bcs->rx_fcs = fcs;
        return procbytes;
 }
 
@@ -308,18 +286,18 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
        struct cardstate *cs = inbuf->cs;
        struct bc_state *bcs = cs->bcs;
        int inputstate = bcs->inputstate;
-       struct sk_buff *skb = bcs->skb;
+       struct sk_buff *skb = bcs->rx_skb;
        unsigned char *src = inbuf->data + inbuf->head;
        unsigned procbytes = 0;
        unsigned char c;
 
        if (!skb) {
                /* skip this block */
-               new_rcv_skb(bcs);
+               gigaset_new_rx_skb(bcs);
                return numbytes;
        }
 
-       while (procbytes < numbytes && skb->len < SBUFSIZE) {
+       while (procbytes < numbytes && skb->len < bcs->rx_bufsize) {
                c = *src++;
                procbytes++;
 
@@ -343,7 +321,7 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
        if (inputstate & INS_have_data) {
                gigaset_skb_rcvd(bcs, skb);
                inputstate &= ~INS_have_data;
-               new_rcv_skb(bcs);
+               gigaset_new_rx_skb(bcs);
        }
 
        bcs->inputstate = inputstate;
index 8f78f15c8ef78798f06a6e4a076a718829b7999c..6fbe8999c4191e6b5b7d1ac78512c1135803f4c5 100644 (file)
@@ -70,7 +70,7 @@
 #define MAX_NUMBER_DIGITS 20
 #define MAX_FMT_IE_LEN 20
 
-/* values for gigaset_capi_appl.connected */
+/* values for bcs->apconnstate */
 #define APCONN_NONE    0       /* inactive/listening */
 #define APCONN_SETUP   1       /* connecting */
 #define APCONN_ACTIVE  2       /* B channel up */
@@ -80,10 +80,10 @@ struct gigaset_capi_appl {
        struct list_head ctrlist;
        struct gigaset_capi_appl *bcnext;
        u16 id;
+       struct capi_register_params rp;
        u16 nextMessageNumber;
        u32 listenInfoMask;
        u32 listenCIPmask;
-       int connected;
 };
 
 /* CAPI specific controller data structure */
@@ -319,6 +319,39 @@ static const char *format_ie(const char *ie)
        return result;
 }
 
+/*
+ * emit DATA_B3_CONF message
+ */
+static void send_data_b3_conf(struct cardstate *cs, struct capi_ctr *ctr,
+                             u16 appl, u16 msgid, int channel,
+                             u16 handle, u16 info)
+{
+       struct sk_buff *cskb;
+       u8 *msg;
+
+       cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
+       if (!cskb) {
+               dev_err(cs->dev, "%s: out of memory\n", __func__);
+               return;
+       }
+       /* frequent message, avoid _cmsg overhead */
+       msg = __skb_put(cskb, CAPI_DATA_B3_CONF_LEN);
+       CAPIMSG_SETLEN(msg, CAPI_DATA_B3_CONF_LEN);
+       CAPIMSG_SETAPPID(msg, appl);
+       CAPIMSG_SETCOMMAND(msg, CAPI_DATA_B3);
+       CAPIMSG_SETSUBCOMMAND(msg,  CAPI_CONF);
+       CAPIMSG_SETMSGID(msg, msgid);
+       CAPIMSG_SETCONTROLLER(msg, ctr->cnr);
+       CAPIMSG_SETPLCI_PART(msg, channel);
+       CAPIMSG_SETNCCI_PART(msg, 1);
+       CAPIMSG_SETHANDLE_CONF(msg, handle);
+       CAPIMSG_SETINFO_CONF(msg, info);
+
+       /* emit message */
+       dump_rawmsg(DEBUG_MCMD, __func__, msg);
+       capi_ctr_handle_message(ctr, appl, cskb);
+}
+
 
 /*
  * driver interface functions
@@ -339,7 +372,6 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
        struct gigaset_capi_ctr *iif = cs->iif;
        struct gigaset_capi_appl *ap = bcs->ap;
        unsigned char *req = skb_mac_header(dskb);
-       struct sk_buff *cskb;
        u16 flags;
 
        /* update statistics */
@@ -351,39 +383,22 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
        }
 
        /* don't send further B3 messages if disconnected */
-       if (ap->connected < APCONN_ACTIVE) {
+       if (bcs->apconnstate < APCONN_ACTIVE) {
                gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack");
                return;
        }
 
-       /* ToDo: honor unset "delivery confirmation" bit */
+       /*
+        * send DATA_B3_CONF if "delivery confirmation" bit was set in request;
+        * otherwise it has already been sent by do_data_b3_req()
+        */
        flags = CAPIMSG_FLAGS(req);
-
-       /* build DATA_B3_CONF message */
-       cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
-       if (!cskb) {
-               dev_err(cs->dev, "%s: out of memory\n", __func__);
-               return;
-       }
-       /* frequent message, avoid _cmsg overhead */
-       CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN);
-       CAPIMSG_SETAPPID(cskb->data, ap->id);
-       CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3);
-       CAPIMSG_SETSUBCOMMAND(cskb->data,  CAPI_CONF);
-       CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req));
-       CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr);
-       CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1);
-       CAPIMSG_SETNCCI_PART(cskb->data, 1);
-       CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req));
-       if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION)
-               CAPIMSG_SETINFO_CONF(cskb->data,
-                                    CapiFlagsNotSupportedByProtocol);
-       else
-               CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR);
-
-       /* emit message */
-       dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data);
-       capi_ctr_handle_message(&iif->ctr, ap->id, cskb);
+       if (flags & CAPI_FLAGS_DELIVERY_CONFIRMATION)
+               send_data_b3_conf(cs, &iif->ctr, ap->id, CAPIMSG_MSGID(req),
+                                 bcs->channel + 1, CAPIMSG_HANDLE_REQ(req),
+                                 (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) ?
+                                       CapiFlagsNotSupportedByProtocol :
+                                       CAPI_NOERROR);
 }
 EXPORT_SYMBOL_GPL(gigaset_skb_sent);
 
@@ -412,7 +427,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
        }
 
        /* don't send further B3 messages if disconnected */
-       if (ap->connected < APCONN_ACTIVE) {
+       if (bcs->apconnstate < APCONN_ACTIVE) {
                gig_dbg(DEBUG_LLDATA, "disconnected, discarding data");
                dev_kfree_skb_any(skb);
                return;
@@ -484,6 +499,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
        u32 actCIPmask;
        struct sk_buff *skb;
        unsigned int msgsize;
+       unsigned long flags;
        int i;
 
        /*
@@ -608,7 +624,14 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
                format_ie(iif->hcmsg.CalledPartyNumber));
 
        /* scan application list for matching listeners */
-       bcs->ap = NULL;
+       spin_lock_irqsave(&bcs->aplock, flags);
+       if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) {
+               dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n",
+                        __func__, bcs->ap, bcs->apconnstate);
+               bcs->ap = NULL;
+               bcs->apconnstate = APCONN_NONE;
+       }
+       spin_unlock_irqrestore(&bcs->aplock, flags);
        actCIPmask = 1 | (1 << iif->hcmsg.CIPValue);
        list_for_each_entry(ap, &iif->appls, ctrlist)
                if (actCIPmask & ap->listenCIPmask) {
@@ -626,10 +649,12 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
                        dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
 
                        /* add to listeners on this B channel, update state */
+                       spin_lock_irqsave(&bcs->aplock, flags);
                        ap->bcnext = bcs->ap;
                        bcs->ap = ap;
                        bcs->chstate |= CHS_NOTIFY_LL;
-                       ap->connected = APCONN_SETUP;
+                       bcs->apconnstate = APCONN_SETUP;
+                       spin_unlock_irqrestore(&bcs->aplock, flags);
 
                        /* emit message */
                        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
@@ -654,7 +679,7 @@ static void send_disconnect_ind(struct bc_state *bcs,
        struct gigaset_capi_ctr *iif = cs->iif;
        struct sk_buff *skb;
 
-       if (ap->connected == APCONN_NONE)
+       if (bcs->apconnstate == APCONN_NONE)
                return;
 
        capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND,
@@ -668,7 +693,6 @@ static void send_disconnect_ind(struct bc_state *bcs,
        }
        capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN));
        dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
-       ap->connected = APCONN_NONE;
        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
 }
 
@@ -685,9 +709,9 @@ static void send_disconnect_b3_ind(struct bc_state *bcs,
        struct sk_buff *skb;
 
        /* nothing to do if no logical connection active */
-       if (ap->connected < APCONN_ACTIVE)
+       if (bcs->apconnstate < APCONN_ACTIVE)
                return;
-       ap->connected = APCONN_SETUP;
+       bcs->apconnstate = APCONN_SETUP;
 
        capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND,
                         ap->nextMessageNumber++,
@@ -714,14 +738,25 @@ void gigaset_isdn_connD(struct bc_state *bcs)
 {
        struct cardstate *cs = bcs->cs;
        struct gigaset_capi_ctr *iif = cs->iif;
-       struct gigaset_capi_appl *ap = bcs->ap;
+       struct gigaset_capi_appl *ap;
        struct sk_buff *skb;
        unsigned int msgsize;
+       unsigned long flags;
 
+       spin_lock_irqsave(&bcs->aplock, flags);
+       ap = bcs->ap;
        if (!ap) {
+               spin_unlock_irqrestore(&bcs->aplock, flags);
                dev_err(cs->dev, "%s: no application\n", __func__);
                return;
        }
+       if (bcs->apconnstate == APCONN_NONE) {
+               spin_unlock_irqrestore(&bcs->aplock, flags);
+               dev_warn(cs->dev, "%s: application %u not connected\n",
+                        __func__, ap->id);
+               return;
+       }
+       spin_unlock_irqrestore(&bcs->aplock, flags);
        while (ap->bcnext) {
                /* this should never happen */
                dev_warn(cs->dev, "%s: dropping extra application %u\n",
@@ -730,11 +765,6 @@ void gigaset_isdn_connD(struct bc_state *bcs)
                                    CapiCallGivenToOtherApplication);
                ap->bcnext = ap->bcnext->bcnext;
        }
-       if (ap->connected == APCONN_NONE) {
-               dev_warn(cs->dev, "%s: application %u not connected\n",
-                        __func__, ap->id);
-               return;
-       }
 
        /* prepare CONNECT_ACTIVE_IND message
         * Note: LLC not supported by device
@@ -772,17 +802,24 @@ void gigaset_isdn_connD(struct bc_state *bcs)
 void gigaset_isdn_hupD(struct bc_state *bcs)
 {
        struct gigaset_capi_appl *ap;
+       unsigned long flags;
 
        /*
         * ToDo: pass on reason code reported by device
         * (requires ev-layer state machine extension to collect
         * ZCAU device reply)
         */
-       for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) {
+       spin_lock_irqsave(&bcs->aplock, flags);
+       while (bcs->ap != NULL) {
+               ap = bcs->ap;
+               bcs->ap = ap->bcnext;
+               spin_unlock_irqrestore(&bcs->aplock, flags);
                send_disconnect_b3_ind(bcs, ap);
                send_disconnect_ind(bcs, ap, 0);
+               spin_lock_irqsave(&bcs->aplock, flags);
        }
-       bcs->ap = NULL;
+       bcs->apconnstate = APCONN_NONE;
+       spin_unlock_irqrestore(&bcs->aplock, flags);
 }
 
 /**
@@ -796,24 +833,21 @@ void gigaset_isdn_connB(struct bc_state *bcs)
 {
        struct cardstate *cs = bcs->cs;
        struct gigaset_capi_ctr *iif = cs->iif;
-       struct gigaset_capi_appl *ap = bcs->ap;
+       struct gigaset_capi_appl *ap;
        struct sk_buff *skb;
+       unsigned long flags;
        unsigned int msgsize;
        u8 command;
 
+       spin_lock_irqsave(&bcs->aplock, flags);
+       ap = bcs->ap;
        if (!ap) {
+               spin_unlock_irqrestore(&bcs->aplock, flags);
                dev_err(cs->dev, "%s: no application\n", __func__);
                return;
        }
-       while (ap->bcnext) {
-               /* this should never happen */
-               dev_warn(cs->dev, "%s: dropping extra application %u\n",
-                        __func__, ap->bcnext->id);
-               send_disconnect_ind(bcs, ap->bcnext,
-                                   CapiCallGivenToOtherApplication);
-               ap->bcnext = ap->bcnext->bcnext;
-       }
-       if (!ap->connected) {
+       if (!bcs->apconnstate) {
+               spin_unlock_irqrestore(&bcs->aplock, flags);
                dev_warn(cs->dev, "%s: application %u not connected\n",
                         __func__, ap->id);
                return;
@@ -825,13 +859,26 @@ void gigaset_isdn_connB(struct bc_state *bcs)
         * CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP
         * Parameters in both cases always: NCCI = 1, NCPI empty
         */
-       if (ap->connected >= APCONN_ACTIVE) {
+       if (bcs->apconnstate >= APCONN_ACTIVE) {
                command = CAPI_CONNECT_B3_ACTIVE;
                msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN;
        } else {
                command = CAPI_CONNECT_B3;
                msgsize = CAPI_CONNECT_B3_IND_BASELEN;
        }
+       bcs->apconnstate = APCONN_ACTIVE;
+
+       spin_unlock_irqrestore(&bcs->aplock, flags);
+
+       while (ap->bcnext) {
+               /* this should never happen */
+               dev_warn(cs->dev, "%s: dropping extra application %u\n",
+                        __func__, ap->bcnext->id);
+               send_disconnect_ind(bcs, ap->bcnext,
+                                   CapiCallGivenToOtherApplication);
+               ap->bcnext = ap->bcnext->bcnext;
+       }
+
        capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND,
                         ap->nextMessageNumber++,
                         iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16));
@@ -842,7 +889,6 @@ void gigaset_isdn_connB(struct bc_state *bcs)
        }
        capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize));
        dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
-       ap->connected = APCONN_ACTIVE;
        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
 }
 
@@ -945,8 +991,64 @@ static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl,
                return;
        }
        ap->id = appl;
+       ap->rp = *rp;
 
        list_add(&ap->ctrlist, &iif->appls);
+       dev_info(cs->dev, "application %u registered\n", ap->id);
+}
+
+/*
+ * remove CAPI application from channel
+ * helper function to keep indentation levels down and stay in 80 columns
+ */
+
+static inline void remove_appl_from_channel(struct bc_state *bcs,
+                                           struct gigaset_capi_appl *ap)
+{
+       struct cardstate *cs = bcs->cs;
+       struct gigaset_capi_appl *bcap;
+       unsigned long flags;
+       int prevconnstate;
+
+       spin_lock_irqsave(&bcs->aplock, flags);
+       bcap = bcs->ap;
+       if (bcap == NULL) {
+               spin_unlock_irqrestore(&bcs->aplock, flags);
+               return;
+       }
+
+       /* check first application on channel */
+       if (bcap == ap) {
+               bcs->ap = ap->bcnext;
+               if (bcs->ap != NULL) {
+                       spin_unlock_irqrestore(&bcs->aplock, flags);
+                       return;
+               }
+
+               /* none left, clear channel state */
+               prevconnstate = bcs->apconnstate;
+               bcs->apconnstate = APCONN_NONE;
+               spin_unlock_irqrestore(&bcs->aplock, flags);
+
+               if (prevconnstate == APCONN_ACTIVE) {
+                       dev_notice(cs->dev, "%s: hanging up channel %u\n",
+                                  __func__, bcs->channel);
+                       gigaset_add_event(cs, &bcs->at_state,
+                                         EV_HUP, NULL, 0, NULL);
+                       gigaset_schedule_event(cs);
+               }
+               return;
+       }
+
+       /* check remaining list */
+       do {
+               if (bcap->bcnext == ap) {
+                       bcap->bcnext = bcap->bcnext->bcnext;
+                       return;
+               }
+               bcap = bcap->bcnext;
+       } while (bcap != NULL);
+       spin_unlock_irqrestore(&bcs->aplock, flags);
 }
 
 /*
@@ -958,19 +1060,19 @@ static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl)
                = container_of(ctr, struct gigaset_capi_ctr, ctr);
        struct cardstate *cs = iif->ctr.driverdata;
        struct gigaset_capi_appl *ap, *tmp;
+       unsigned ch;
 
        list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist)
                if (ap->id == appl) {
-                       if (ap->connected != APCONN_NONE) {
-                               dev_err(cs->dev,
-                                       "%s: application %u still connected\n",
-                                       __func__, ap->id);
-                               /* ToDo: clear active connection */
-                       }
+                       /* remove from any channels */
+                       for (ch = 0; ch < cs->channels; ch++)
+                               remove_appl_from_channel(&cs->bcs[ch], ap);
+
+                       /* remove from registration list */
                        list_del(&ap->ctrlist);
                        kfree(ap);
+                       dev_info(cs->dev, "application %u released\n", appl);
                }
-
 }
 
 /*
@@ -1149,7 +1251,8 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
        char **commands;
        char *s;
        u8 *pp;
-       int i, l;
+       unsigned long flags;
+       int i, l, lbc, lhlc;
        u16 info;
 
        /* decode message */
@@ -1164,8 +1267,18 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
                send_conf(iif, ap, skb, CapiNoPlciAvailable);
                return;
        }
+       spin_lock_irqsave(&bcs->aplock, flags);
+       if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE)
+               dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n",
+                        __func__, bcs->ap, bcs->apconnstate);
        ap->bcnext = NULL;
        bcs->ap = ap;
+       bcs->apconnstate = APCONN_SETUP;
+       spin_unlock_irqrestore(&bcs->aplock, flags);
+
+       bcs->rx_bufsize = ap->rp.datablklen;
+       dev_kfree_skb(bcs->rx_skb);
+       gigaset_new_rx_skb(bcs);
        cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8;
 
        /* build command table */
@@ -1273,42 +1386,59 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
                goto error;
        }
 
-       /* check/encode parameter: BC */
-       if (cmsg->BC && cmsg->BC[0]) {
-               /* explicit BC overrides CIP */
-               l = 2*cmsg->BC[0] + 7;
+       /*
+        * check/encode parameters: BC & HLC
+        * must be encoded together as device doesn't accept HLC separately
+        * explicit parameters override values derived from CIP
+        */
+
+       /* determine lengths */
+       if (cmsg->BC && cmsg->BC[0])            /* BC specified explicitly */
+               lbc = 2*cmsg->BC[0];
+       else if (cip2bchlc[cmsg->CIPValue].bc)  /* BC derived from CIP */
+               lbc = strlen(cip2bchlc[cmsg->CIPValue].bc);
+       else                                    /* no BC */
+               lbc = 0;
+       if (cmsg->HLC && cmsg->HLC[0])          /* HLC specified explicitly */
+               lhlc = 2*cmsg->HLC[0];
+       else if (cip2bchlc[cmsg->CIPValue].hlc) /* HLC derived from CIP */
+               lhlc = strlen(cip2bchlc[cmsg->CIPValue].hlc);
+       else                                    /* no HLC */
+               lhlc = 0;
+
+       if (lbc) {
+               /* have BC: allocate and assemble command string */
+               l = lbc + 7;            /* "^SBC=" + value + "\r" + null byte */
+               if (lhlc)
+                       l += lhlc + 7;  /* ";^SHLC=" + value */
                commands[AT_BC] = kmalloc(l, GFP_KERNEL);
                if (!commands[AT_BC])
                        goto oom;
                strcpy(commands[AT_BC], "^SBC=");
-               decode_ie(cmsg->BC, commands[AT_BC]+5);
+               if (cmsg->BC && cmsg->BC[0])    /* BC specified explicitly */
+                       decode_ie(cmsg->BC, commands[AT_BC] + 5);
+               else                            /* BC derived from CIP */
+                       strcpy(commands[AT_BC] + 5,
+                              cip2bchlc[cmsg->CIPValue].bc);
+               if (lhlc) {
+                       strcpy(commands[AT_BC] + lbc + 5, ";^SHLC=");
+                       if (cmsg->HLC && cmsg->HLC[0])
+                               /* HLC specified explicitly */
+                               decode_ie(cmsg->HLC,
+                                         commands[AT_BC] + lbc + 12);
+                       else    /* HLC derived from CIP */
+                               strcpy(commands[AT_BC] + lbc + 12,
+                                      cip2bchlc[cmsg->CIPValue].hlc);
+               }
                strcpy(commands[AT_BC] + l - 2, "\r");
-       } else if (cip2bchlc[cmsg->CIPValue].bc) {
-               l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7;
-               commands[AT_BC] = kmalloc(l, GFP_KERNEL);
-               if (!commands[AT_BC])
-                       goto oom;
-               snprintf(commands[AT_BC], l, "^SBC=%s\r",
-                        cip2bchlc[cmsg->CIPValue].bc);
-       }
-
-       /* check/encode parameter: HLC */
-       if (cmsg->HLC && cmsg->HLC[0]) {
-               /* explicit HLC overrides CIP */
-               l = 2*cmsg->HLC[0] + 7;
-               commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
-               if (!commands[AT_HLC])
-                       goto oom;
-               strcpy(commands[AT_HLC], "^SHLC=");
-               decode_ie(cmsg->HLC, commands[AT_HLC]+5);
-               strcpy(commands[AT_HLC] + l - 2, "\r");
-       } else if (cip2bchlc[cmsg->CIPValue].hlc) {
-               l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7;
-               commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
-               if (!commands[AT_HLC])
-                       goto oom;
-               snprintf(commands[AT_HLC], l, "^SHLC=%s\r",
-                        cip2bchlc[cmsg->CIPValue].hlc);
+       } else {
+               /* no BC */
+               if (lhlc) {
+                       dev_notice(cs->dev, "%s: cannot set HLC without BC\n",
+                                  "CONNECT_REQ");
+                       info = CapiIllMessageParmCoding; /* ? */
+                       goto error;
+               }
        }
 
        /* check/encode parameter: B Protocol */
@@ -1322,13 +1452,13 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
                        bcs->proto2 = L2_HDLC;
                        break;
                case 1:
-                       bcs->proto2 = L2_BITSYNC;
+                       bcs->proto2 = L2_VOICE;
                        break;
                default:
                        dev_warn(cs->dev,
                            "B1 Protocol %u unsupported, using Transparent\n",
                                 cmsg->B1protocol);
-                       bcs->proto2 = L2_BITSYNC;
+                       bcs->proto2 = L2_VOICE;
                }
                if (cmsg->B2protocol != 1)
                        dev_warn(cs->dev,
@@ -1382,7 +1512,6 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
                goto error;
        }
        gigaset_schedule_event(cs);
-       ap->connected = APCONN_SETUP;
        send_conf(iif, ap, skb, CapiSuccess);
        return;
 
@@ -1410,6 +1539,7 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
        _cmsg *cmsg = &iif->acmsg;
        struct bc_state *bcs;
        struct gigaset_capi_appl *oap;
+       unsigned long flags;
        int channel;
 
        /* decode message */
@@ -1429,12 +1559,24 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
        switch (cmsg->Reject) {
        case 0:         /* Accept */
                /* drop all competing applications, keep only this one */
-               for (oap = bcs->ap; oap != NULL; oap = oap->bcnext)
-                       if (oap != ap)
+               spin_lock_irqsave(&bcs->aplock, flags);
+               while (bcs->ap != NULL) {
+                       oap = bcs->ap;
+                       bcs->ap = oap->bcnext;
+                       if (oap != ap) {
+                               spin_unlock_irqrestore(&bcs->aplock, flags);
                                send_disconnect_ind(bcs, oap,
                                        CapiCallGivenToOtherApplication);
+                               spin_lock_irqsave(&bcs->aplock, flags);
+                       }
+               }
                ap->bcnext = NULL;
                bcs->ap = ap;
+               spin_unlock_irqrestore(&bcs->aplock, flags);
+
+               bcs->rx_bufsize = ap->rp.datablklen;
+               dev_kfree_skb(bcs->rx_skb);
+               gigaset_new_rx_skb(bcs);
                bcs->chstate |= CHS_NOTIFY_LL;
 
                /* check/encode B channel protocol */
@@ -1448,13 +1590,13 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
                                bcs->proto2 = L2_HDLC;
                                break;
                        case 1:
-                               bcs->proto2 = L2_BITSYNC;
+                               bcs->proto2 = L2_VOICE;
                                break;
                        default:
                                dev_warn(cs->dev,
                        "B1 Protocol %u unsupported, using Transparent\n",
                                         cmsg->B1protocol);
-                               bcs->proto2 = L2_BITSYNC;
+                               bcs->proto2 = L2_VOICE;
                        }
                        if (cmsg->B2protocol != 1)
                                dev_warn(cs->dev,
@@ -1502,31 +1644,45 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
                send_disconnect_ind(bcs, ap, 0);
 
                /* remove it from the list of listening apps */
+               spin_lock_irqsave(&bcs->aplock, flags);
                if (bcs->ap == ap) {
                        bcs->ap = ap->bcnext;
-                       if (bcs->ap == NULL)
+                       if (bcs->ap == NULL) {
                                /* last one: stop ev-layer hupD notifications */
+                               bcs->apconnstate = APCONN_NONE;
                                bcs->chstate &= ~CHS_NOTIFY_LL;
+                       }
+                       spin_unlock_irqrestore(&bcs->aplock, flags);
                        return;
                }
                for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) {
                        if (oap->bcnext == ap) {
                                oap->bcnext = oap->bcnext->bcnext;
+                               spin_unlock_irqrestore(&bcs->aplock, flags);
                                return;
                        }
                }
+               spin_unlock_irqrestore(&bcs->aplock, flags);
                dev_err(cs->dev, "%s: application %u not found\n",
                        __func__, ap->id);
                return;
 
        default:                /* Reject */
                /* drop all competing applications, keep only this one */
-               for (oap = bcs->ap; oap != NULL; oap = oap->bcnext)
-                       if (oap != ap)
+               spin_lock_irqsave(&bcs->aplock, flags);
+               while (bcs->ap != NULL) {
+                       oap = bcs->ap;
+                       bcs->ap = oap->bcnext;
+                       if (oap != ap) {
+                               spin_unlock_irqrestore(&bcs->aplock, flags);
                                send_disconnect_ind(bcs, oap,
                                        CapiCallGivenToOtherApplication);
+                               spin_lock_irqsave(&bcs->aplock, flags);
+                       }
+               }
                ap->bcnext = NULL;
                bcs->ap = ap;
+               spin_unlock_irqrestore(&bcs->aplock, flags);
 
                /* reject call - will trigger DISCONNECT_IND for this app */
                dev_info(cs->dev, "%s: Reject=%x\n",
@@ -1549,6 +1705,7 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
 {
        struct cardstate *cs = iif->ctr.driverdata;
        _cmsg *cmsg = &iif->acmsg;
+       struct bc_state *bcs;
        int channel;
 
        /* decode message */
@@ -1563,9 +1720,10 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
                send_conf(iif, ap, skb, CapiIllContrPlciNcci);
                return;
        }
+       bcs = &cs->bcs[channel-1];
 
        /* mark logical connection active */
-       ap->connected = APCONN_ACTIVE;
+       bcs->apconnstate = APCONN_ACTIVE;
 
        /* build NCCI: always 1 (one B3 connection only) */
        cmsg->adr.adrNCCI |= 1 << 16;
@@ -1611,7 +1769,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
 
        if (cmsg->Reject) {
                /* Reject: clear B3 connect received flag */
-               ap->connected = APCONN_SETUP;
+               bcs->apconnstate = APCONN_SETUP;
 
                /* trigger hangup, causing eventual DISCONNECT_IND */
                if (!gigaset_add_event(cs, &bcs->at_state,
@@ -1683,11 +1841,11 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
        }
 
        /* skip if DISCONNECT_IND already sent */
-       if (!ap->connected)
+       if (!bcs->apconnstate)
                return;
 
        /* check for active logical connection */
-       if (ap->connected >= APCONN_ACTIVE) {
+       if (bcs->apconnstate >= APCONN_ACTIVE) {
                /*
                 * emit DISCONNECT_B3_IND with cause 0x3301
                 * use separate cmsg structure, as the content of iif->acmsg
@@ -1736,6 +1894,7 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
 {
        struct cardstate *cs = iif->ctr.driverdata;
        _cmsg *cmsg = &iif->acmsg;
+       struct bc_state *bcs;
        int channel;
 
        /* decode message */
@@ -1751,17 +1910,17 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
                send_conf(iif, ap, skb, CapiIllContrPlciNcci);
                return;
        }
+       bcs = &cs->bcs[channel-1];
 
        /* reject if logical connection not active */
-       if (ap->connected < APCONN_ACTIVE) {
+       if (bcs->apconnstate < APCONN_ACTIVE) {
                send_conf(iif, ap, skb,
                          CapiMessageNotSupportedInCurrentState);
                return;
        }
 
        /* trigger hangup, causing eventual DISCONNECT_B3_IND */
-       if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state,
-                              EV_HUP, NULL, 0, NULL)) {
+       if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {
                send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
                return;
        }
@@ -1782,11 +1941,14 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
                           struct sk_buff *skb)
 {
        struct cardstate *cs = iif->ctr.driverdata;
+       struct bc_state *bcs;
        int channel = CAPIMSG_PLCI_PART(skb->data);
        u16 ncci = CAPIMSG_NCCI_PART(skb->data);
        u16 msglen = CAPIMSG_LEN(skb->data);
        u16 datalen = CAPIMSG_DATALEN(skb->data);
        u16 flags = CAPIMSG_FLAGS(skb->data);
+       u16 msgid = CAPIMSG_MSGID(skb->data);
+       u16 handle = CAPIMSG_HANDLE_REQ(skb->data);
 
        /* frequent message, avoid _cmsg overhead */
        dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data);
@@ -1802,6 +1964,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
                send_conf(iif, ap, skb, CapiIllContrPlciNcci);
                return;
        }
+       bcs = &cs->bcs[channel-1];
        if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64)
                dev_notice(cs->dev, "%s: unexpected length %d\n",
                           "DATA_B3_REQ", msglen);
@@ -1821,7 +1984,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
        }
 
        /* reject if logical connection not active */
-       if (ap->connected < APCONN_ACTIVE) {
+       if (bcs->apconnstate < APCONN_ACTIVE) {
                send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState);
                return;
        }
@@ -1832,17 +1995,19 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
        skb_pull(skb, msglen);
 
        /* pass to device-specific module */
-       if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) {
+       if (cs->ops->send_skb(bcs, skb) < 0) {
                send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
                return;
        }
 
-       /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */
-
        /*
-        * ToDo: honor unset "delivery confirmation" bit
-        * (send DATA_B3_CONF immediately?)
+        * DATA_B3_CONF will be sent by gigaset_skb_sent() only if "delivery
+        * confirmation" bit is set; otherwise we have to send it now
         */
+       if (!(flags & CAPI_FLAGS_DELIVERY_CONFIRMATION))
+               send_data_b3_conf(cs, &iif->ctr, ap->id, msgid, channel, handle,
+                                 flags ? CapiFlagsNotSupportedByProtocol
+                                       : CAPI_NOERROR);
 }
 
 /*
index f6f45f2219209781aa6955153d494060f7f941ff..5d4befb81057a1c7675cb86d05b8cb82737495ec 100644 (file)
@@ -399,8 +399,8 @@ static void gigaset_freebcs(struct bc_state *bcs)
        gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
        clear_at_state(&bcs->at_state);
        gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
-       dev_kfree_skb(bcs->skb);
-       bcs->skb = NULL;
+       dev_kfree_skb(bcs->rx_skb);
+       bcs->rx_skb = NULL;
 
        for (i = 0; i < AT_NUM; ++i) {
                kfree(bcs->commands[i]);
@@ -634,19 +634,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
        bcs->emptycount = 0;
 #endif
 
-       gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
-       bcs->fcs = PPP_INITFCS;
+       bcs->rx_bufsize = 0;
+       bcs->rx_skb = NULL;
+       bcs->rx_fcs = PPP_INITFCS;
        bcs->inputstate = 0;
-       if (cs->ignoreframes) {
-               bcs->skb = NULL;
-       } else {
-               bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
-               if (bcs->skb != NULL)
-                       skb_reserve(bcs->skb, cs->hw_hdr_len);
-               else
-                       pr_err("out of memory\n");
-       }
-
        bcs->channel = channel;
        bcs->cs = cs;
 
@@ -658,16 +649,15 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
        for (i = 0; i < AT_NUM; ++i)
                bcs->commands[i] = NULL;
 
+       spin_lock_init(&bcs->aplock);
+       bcs->ap = NULL;
+       bcs->apconnstate = 0;
+
        gig_dbg(DEBUG_INIT, "  setting up bcs[%d]->hw", channel);
        if (cs->ops->initbcshw(bcs))
                return bcs;
 
        gig_dbg(DEBUG_INIT, "  failed");
-
-       gig_dbg(DEBUG_INIT, "  freeing bcs[%d]->skb", channel);
-       dev_kfree_skb(bcs->skb);
-       bcs->skb = NULL;
-
        return NULL;
 }
 
@@ -839,14 +829,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs)
        bcs->emptycount = 0;
 #endif
 
-       bcs->fcs = PPP_INITFCS;
+       bcs->rx_fcs = PPP_INITFCS;
        bcs->chstate = 0;
 
        bcs->ignore = cs->ignoreframes;
-       if (bcs->ignore) {
-               dev_kfree_skb(bcs->skb);
-               bcs->skb = NULL;
-       }
+       dev_kfree_skb(bcs->rx_skb);
+       bcs->rx_skb = NULL;
 
        cs->ops->reinitbcshw(bcs);
 }
index 206c380c52358c724aa72a06ce6c7405d9ff7164..ceaef9a04a42410b876de74558a51301d3a89c3e 100644 (file)
@@ -282,9 +282,7 @@ struct reply_t gigaset_tab_cid[] =
 /* dial */
 {EV_DIAL,       -1,  -1, -1,                    -1, -1, {ACT_DIAL} },
 {RSP_INIT,       0,   0, SEQ_DIAL,             601,  5, {ACT_CMD+AT_BC} },
-{RSP_OK,       601, 601, -1,                   602,  5, {ACT_CMD+AT_HLC} },
-{RSP_NULL,     602, 602, -1,                   603,  5, {ACT_CMD+AT_PROTO} },
-{RSP_OK,       602, 602, -1,                   603,  5, {ACT_CMD+AT_PROTO} },
+{RSP_OK,       601, 601, -1,                   603,  5, {ACT_CMD+AT_PROTO} },
 {RSP_OK,       603, 603, -1,                   604,  5, {ACT_CMD+AT_TYPE} },
 {RSP_OK,       604, 604, -1,                   605,  5, {ACT_CMD+AT_MSN} },
 {RSP_NULL,     605, 605, -1,                   606,  5, {ACT_CMD+AT_CLIP} },
index 05947f9c18496b8b9b197cbe61c6696f450ca24d..8738b0821fc9c29ea7ddcbec6a888db709766272 100644 (file)
 #define MAX_EVENTS 64          /* size of event queue */
 
 #define RBUFSIZE 8192
-#define SBUFSIZE 4096          /* sk_buff payload size */
-
-#define TRANSBUFSIZE 768       /* bytes per skb for transparent receive */
-#define MAX_BUF_SIZE (SBUFSIZE - 2)    /* Max. size of a data packet from LL */
 
 /* compile time options */
 #define GIG_MAJOR 0
@@ -190,10 +186,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
 #define AT_BC          3
 #define AT_PROTO       4
 #define AT_TYPE                5
-#define AT_HLC         6
-#define AT_CLIP                7
+#define AT_CLIP                6
 /* total number */
-#define AT_NUM         8
+#define AT_NUM         7
 
 /* variables in struct at_state_t */
 #define VAR_ZSAU       0
@@ -380,8 +375,10 @@ struct bc_state {
 
        struct at_state_t at_state;
 
-       __u16 fcs;
-       struct sk_buff *skb;
+       /* receive buffer */
+       unsigned rx_bufsize;            /* max size accepted by application */
+       struct sk_buff *rx_skb;
+       __u16 rx_fcs;
        int inputstate;                 /* see INS_XXXX */
 
        int channel;
@@ -406,7 +403,9 @@ struct bc_state {
                struct bas_bc_state *bas;       /* usb hardware driver (base) */
        } hw;
 
-       void *ap;                       /* LL application structure */
+       void *ap;                       /* associated LL application */
+       int apconnstate;                /* LL application connection state */
+       spinlock_t aplock;
 };
 
 struct cardstate {
@@ -801,8 +800,23 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs)
        gigaset_schedule_event(bcs->cs);
 }
 
-/* handling routines for sk_buff */
-/* ============================= */
+/* set up next receive skb for data mode */
+static inline struct sk_buff *gigaset_new_rx_skb(struct bc_state *bcs)
+{
+       struct cardstate *cs = bcs->cs;
+       unsigned short hw_hdr_len = cs->hw_hdr_len;
+
+       if (bcs->ignore) {
+               bcs->rx_skb = NULL;
+       } else {
+               bcs->rx_skb = dev_alloc_skb(bcs->rx_bufsize + hw_hdr_len);
+               if (bcs->rx_skb == NULL)
+                       dev_warn(cs->dev, "could not allocate skb\n");
+               else
+                       skb_reserve(bcs->rx_skb, hw_hdr_len);
+       }
+       return bcs->rx_skb;
+}
 
 /* append received bytes to inbuf */
 int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
index c22e5ace8276a99fe39188eb13941e56f6b07cb4..f01c3c2e2e46eb5f5194fa8afa8ba78e8d3b8532 100644 (file)
 #include "gigaset.h"
 #include <linux/isdnif.h>
 
+#define SBUFSIZE       4096    /* sk_buff payload size */
+#define TRANSBUFSIZE   768     /* bytes per skb for transparent receive */
 #define HW_HDR_LEN     2       /* Header size used to store ack info */
+#define MAX_BUF_SIZE   (SBUFSIZE - HW_HDR_LEN) /* max data packet from LL */
 
 /* == Handling of I4L IO =====================================================*/
 
@@ -231,6 +234,15 @@ static int command_from_LL(isdn_ctrl *cntrl)
                        dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
                        return -EBUSY;
                }
+               switch (bcs->proto2) {
+               case L2_HDLC:
+                       bcs->rx_bufsize = SBUFSIZE;
+                       break;
+               default:                        /* assume transparent */
+                       bcs->rx_bufsize = TRANSBUFSIZE;
+               }
+               dev_kfree_skb(bcs->rx_skb);
+               gigaset_new_rx_skb(bcs);
 
                commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);
                if (!commands) {
@@ -314,6 +326,15 @@ static int command_from_LL(isdn_ctrl *cntrl)
                        return -EINVAL;
                }
                bcs = cs->bcs + ch;
+               switch (bcs->proto2) {
+               case L2_HDLC:
+                       bcs->rx_bufsize = SBUFSIZE;
+                       break;
+               default:                        /* assume transparent */
+                       bcs->rx_bufsize = TRANSBUFSIZE;
+               }
+               dev_kfree_skb(bcs->rx_skb);
+               gigaset_new_rx_skb(bcs);
                if (!gigaset_add_event(cs, &bcs->at_state,
                                       EV_ACCEPT, NULL, 0, NULL))
                        return -ENOMEM;
index 16fd3bd488834101b74a7dd316f82b6badbe8b5d..2dfd346fc889abe9f423873551647c21d319038e 100644 (file)
@@ -500,19 +500,18 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)
  */
 static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
 {
-       bcs->fcs = crc_ccitt_byte(bcs->fcs, c);
-       if (unlikely(bcs->skb == NULL)) {
+       bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c);
+       if (bcs->rx_skb == NULL)
                /* skipping */
                return;
-       }
-       if (unlikely(bcs->skb->len == SBUFSIZE)) {
+       if (bcs->rx_skb->len >= bcs->rx_bufsize) {
                dev_warn(bcs->cs->dev, "received oversized packet discarded\n");
                bcs->hw.bas->giants++;
-               dev_kfree_skb_any(bcs->skb);
-               bcs->skb = NULL;
+               dev_kfree_skb_any(bcs->rx_skb);
+               bcs->rx_skb = NULL;
                return;
        }
-       *__skb_put(bcs->skb, 1) = c;
+       *__skb_put(bcs->rx_skb, 1) = c;
 }
 
 /* hdlc_flush
@@ -521,18 +520,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
 static inline void hdlc_flush(struct bc_state *bcs)
 {
        /* clear skb or allocate new if not skipping */
-       if (likely(bcs->skb != NULL))
-               skb_trim(bcs->skb, 0);
-       else if (!bcs->ignore) {
-               bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len);
-               if (bcs->skb)
-                       skb_reserve(bcs->skb, bcs->cs->hw_hdr_len);
-               else
-                       dev_err(bcs->cs->dev, "could not allocate skb\n");
-       }
+       if (bcs->rx_skb != NULL)
+               skb_trim(bcs->rx_skb, 0);
+       else
+               gigaset_new_rx_skb(bcs);
 
        /* reset packet state */
-       bcs->fcs = PPP_INITFCS;
+       bcs->rx_fcs = PPP_INITFCS;
 }
 
 /* hdlc_done
@@ -549,7 +543,7 @@ static inline void hdlc_done(struct bc_state *bcs)
                hdlc_flush(bcs);
                return;
        }
-       procskb = bcs->skb;
+       procskb = bcs->rx_skb;
        if (procskb == NULL) {
                /* previous error */
                gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
@@ -560,8 +554,8 @@ static inline void hdlc_done(struct bc_state *bcs)
                bcs->hw.bas->runts++;
                dev_kfree_skb_any(procskb);
                gigaset_isdn_rcv_err(bcs);
-       } else if (bcs->fcs != PPP_GOODFCS) {
-               dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs);
+       } else if (bcs->rx_fcs != PPP_GOODFCS) {
+               dev_notice(cs->dev, "frame check error\n");
                bcs->hw.bas->fcserrs++;
                dev_kfree_skb_any(procskb);
                gigaset_isdn_rcv_err(bcs);
@@ -574,13 +568,8 @@ static inline void hdlc_done(struct bc_state *bcs)
                bcs->hw.bas->goodbytes += len;
                gigaset_skb_rcvd(bcs, procskb);
        }
-
-       bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
-       if (bcs->skb)
-               skb_reserve(bcs->skb, cs->hw_hdr_len);
-       else
-               dev_err(cs->dev, "could not allocate skb\n");
-       bcs->fcs = PPP_INITFCS;
+       gigaset_new_rx_skb(bcs);
+       bcs->rx_fcs = PPP_INITFCS;
 }
 
 /* hdlc_frag
@@ -597,8 +586,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
        dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
        bcs->hw.bas->alignerrs++;
        gigaset_isdn_rcv_err(bcs);
-       __skb_trim(bcs->skb, 0);
-       bcs->fcs = PPP_INITFCS;
+       __skb_trim(bcs->rx_skb, 0);
+       bcs->rx_fcs = PPP_INITFCS;
 }
 
 /* bit counts lookup table for HDLC bit unstuffing
@@ -847,7 +836,6 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
 static inline void trans_receive(unsigned char *src, unsigned count,
                                 struct bc_state *bcs)
 {
-       struct cardstate *cs = bcs->cs;
        struct sk_buff *skb;
        int dobytes;
        unsigned char *dst;
@@ -857,17 +845,11 @@ static inline void trans_receive(unsigned char *src, unsigned count,
                hdlc_flush(bcs);
                return;
        }
-       skb = bcs->skb;
-       if (unlikely(skb == NULL)) {
-               bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
-               if (!skb) {
-                       dev_err(cs->dev, "could not allocate skb\n");
-                       return;
-               }
-               skb_reserve(skb, cs->hw_hdr_len);
-       }
+       skb = bcs->rx_skb;
+       if (skb == NULL)
+               skb = gigaset_new_rx_skb(bcs);
        bcs->hw.bas->goodbytes += skb->len;
-       dobytes = TRANSBUFSIZE - skb->len;
+       dobytes = bcs->rx_bufsize - skb->len;
        while (count > 0) {
                dst = skb_put(skb, count < dobytes ? count : dobytes);
                while (count > 0 && dobytes > 0) {
@@ -879,14 +861,10 @@ static inline void trans_receive(unsigned char *src, unsigned count,
                        dump_bytes(DEBUG_STREAM_DUMP,
                                   "rcv data", skb->data, skb->len);
                        gigaset_skb_rcvd(bcs, skb);
-                       bcs->skb = skb =
-                               dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
-                       if (!skb) {
-                               dev_err(cs->dev, "could not allocate skb\n");
+                       skb = gigaset_new_rx_skb(bcs);
+                       if (skb == NULL)
                                return;
-                       }
-                       skb_reserve(skb, cs->hw_hdr_len);
-                       dobytes = TRANSBUFSIZE;
+                       dobytes = bcs->rx_bufsize;
                }
        }
 }
index b3b7e2879bac25873da4d2666567f2c52fae434f..8700474747e8cd0251bc54f99f80cb2a7b8eb8e1 100644 (file)
@@ -97,8 +97,10 @@ static int write_reg(struct hfcsusb *hw, __u8 reg, __u8 val)
                        hw->name, __func__, reg, val);
 
        spin_lock(&hw->ctrl_lock);
-       if (hw->ctrl_cnt >= HFC_CTRL_BUFSIZE)
+       if (hw->ctrl_cnt >= HFC_CTRL_BUFSIZE) {
+               spin_unlock(&hw->ctrl_lock);
                return 1;
+       }
        buf = &hw->ctrl_buff[hw->ctrl_in_idx];
        buf->hfcs_reg = reg;
        buf->reg_val = val;
index 0a3553df065fcd38d884e939e040486760073de7..54ae71a907f937c8fcf3d443bf79d4a43a5499bd 100644 (file)
@@ -320,12 +320,12 @@ inittiger(struct tiger_hw *card)
                return -ENOMEM;
        }
        for (i = 0; i < 2; i++) {
-               card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_KERNEL);
+               card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_ATOMIC);
                if (!card->bc[i].hsbuf) {
                        pr_info("%s: no B%d send buffer\n", card->name, i + 1);
                        return -ENOMEM;
                }
-               card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_KERNEL);
+               card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_ATOMIC);
                if (!card->bc[i].hrbuf) {
                        pr_info("%s: no B%d recv buffer\n", card->name, i + 1);
                        return -ENOMEM;
index 72eb92647c1b15e2619f1969892196240a5d2fb2..feec8d89d719c07395ed0e5aa7b02fd6e7fb32c0 100644 (file)
@@ -187,12 +187,13 @@ void
 hysdn_rx_netpkt(hysdn_card * card, unsigned char *buf, unsigned short len)
 {
        struct net_local *lp = card->netif;
-       struct net_device *dev = lp->dev;
+       struct net_device *dev;
        struct sk_buff *skb;
 
        if (!lp)
                return;         /* non existing device */
 
+       dev = lp->dev;
        dev->stats.rx_bytes += len;
 
        skb = dev_alloc_skb(len);
index 286b501a3573d3b7d0d4cec872fa7b40008c83d5..5dcdf9d69b3abae8d0370ccbe1a0d913c716e7d1 100644 (file)
@@ -742,7 +742,6 @@ failed_unregister_dev_file:
        for (i--; i >= 0; i--)
                device_remove_file(&led->client->dev, bd2802_attributes[i]);
 failed_free:
-       i2c_set_clientdata(client, NULL);
        kfree(led);
 
        return ret;
@@ -759,7 +758,6 @@ static int __exit bd2802_remove(struct i2c_client *client)
                bd2802_disable_adv_conf(led);
        for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++)
                device_remove_file(&led->client->dev, bd2802_attributes[i]);
-       i2c_set_clientdata(client, NULL);
        kfree(led);
 
        return 0;
index 932a58da76c4e97cba12a3c7b657b72dafa70e86..9010c054615e414fa5c236a8fe2cc4a700a00757 100644 (file)
@@ -432,7 +432,6 @@ static int __devexit lp3944_remove(struct i2c_client *client)
                }
 
        kfree(data);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index 6682175fa9f7c4e3c5a91d99120c83b2003f6b9a..43d08756d823556b26f5c531d6837ff89818964b 100644 (file)
@@ -320,10 +320,8 @@ static int pca9532_probe(struct i2c_client *client,
        mutex_init(&data->update_lock);
 
        err = pca9532_configure(client, data, pca9532_pdata);
-       if (err) {
+       if (err)
                kfree(data);
-               i2c_set_clientdata(client, NULL);
-       }
 
        return err;
 }
@@ -351,7 +349,6 @@ static int pca9532_remove(struct i2c_client *client)
                }
 
        kfree(data);
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index 8ff50f234190a38129342d743a14c8c7c201ad6c..66aa3e8e786f545c4db0e6bd4318a173a792fc1e 100644 (file)
@@ -342,7 +342,6 @@ exit:
        }
 
        kfree(pca955x);
-       i2c_set_clientdata(client, NULL);
 
        return err;
 }
@@ -358,7 +357,6 @@ static int __devexit pca955x_remove(struct i2c_client *client)
        }
 
        kfree(pca955x);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index 97147804a49cefc2e6b8864da44be7de13ca0832..b6e7ddc09d76573eb0b423747bb613ce16599a7d 100644 (file)
@@ -492,8 +492,8 @@ static void macio_pci_add_devices(struct macio_chip *chip)
        }
 
        /* Add media bay devices if any */
-       pnode = mbdev->ofdev.dev.of_node;
-       if (mbdev)
+       if (mbdev) {
+               pnode = mbdev->ofdev.dev.of_node;
                for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) {
                        if (macio_skip_device(np))
                                continue;
@@ -502,10 +502,11 @@ static void macio_pci_add_devices(struct macio_chip *chip)
                                                 mbdev,  root_res) == NULL)
                                of_node_put(np);
                }
+       }
 
        /* Add serial ports if any */
-       pnode = sdev->ofdev.dev.of_node;
        if (sdev) {
+               pnode = sdev->ofdev.dev.of_node;
                for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) {
                        if (macio_skip_device(np))
                                continue;
@@ -525,7 +526,6 @@ static void macio_pci_add_devices(struct macio_chip *chip)
 int macio_register_driver(struct macio_driver *drv)
 {
        /* initialize common driver fields */
-       drv->driver.name = drv->name;
        drv->driver.bus = &macio_bus_type;
 
        /* register with core */
index 288acce76b74ec36d8324d2284439c9592cbd3c7..2fd435bc542e0db14a8488cbe97dc9380768dc72 100644 (file)
@@ -728,8 +728,10 @@ static struct of_device_id media_bay_match[] =
 
 static struct macio_driver media_bay_driver =
 {
-       .name           = "media-bay",
-       .match_table    = media_bay_match,
+       .driver = {
+               .name           = "media-bay",
+               .of_match_table = media_bay_match,
+       },
        .probe          = media_bay_attach,
        .suspend        = media_bay_suspend,
        .resume         = media_bay_resume
index 12946c5f583f53526654b58a41138595f0f0afc9..53cce3a5da2336b97fd94e0bd55123be2968adbf 100644 (file)
@@ -584,9 +584,11 @@ static struct of_device_id rackmeter_match[] = {
 };
 
 static struct macio_driver rackmeter_driver = {
-       .name = "rackmeter",
-       .owner = THIS_MODULE,
-       .match_table = rackmeter_match,
+       .driver = {
+               .name = "rackmeter",
+               .owner = THIS_MODULE,
+               .of_match_table = rackmeter_match,
+       },
        .probe = rackmeter_probe,
        .remove = __devexit_p(rackmeter_remove),
        .shutdown = rackmeter_shutdown,
index 16d82f17ae82b3a2e0f5a5e37a0a73e18e51e7b5..c42eeb43042daa92d9f04e22b2205ce6d1d2a33d 100644 (file)
@@ -182,7 +182,6 @@ remove_thermostat(struct i2c_client *client)
 
        thermostat = NULL;
 
-       i2c_set_clientdata(client, NULL);
        kfree(th);
 
        return 0;
@@ -400,7 +399,6 @@ static int probe_thermostat(struct i2c_client *client,
        rc = read_reg(th, CONFIG_REG);
        if (rc < 0) {
                dev_err(&client->dev, "Thermostat failed to read config!\n");
-               i2c_set_clientdata(client, NULL);
                kfree(th);
                return -ENODEV;
        }
index d8257d35afde91c225b49bad6f0cc9885cf3fc69..647c6add2193e63d9bcec2be088ac2f28096a962 100644 (file)
@@ -107,10 +107,8 @@ static int wf_lm75_probe(struct i2c_client *client,
        i2c_set_clientdata(client, lm);
 
        rc = wf_register_sensor(&lm->sens);
-       if (rc) {
-               i2c_set_clientdata(client, NULL);
+       if (rc)
                kfree(lm);
-       }
 
        return rc;
 }
@@ -216,7 +214,6 @@ static int wf_lm75_remove(struct i2c_client *client)
        /* release sensor */
        wf_unregister_sensor(&lm->sens);
 
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index b486eb929fde725fb9e0271d4af46cdc241c2113..8204113268f471db6021ffa7915be03272a0c40c 100644 (file)
@@ -81,7 +81,6 @@ static int wf_max6690_probe(struct i2c_client *client,
 
        rc = wf_register_sensor(&max->sens);
        if (rc) {
-               i2c_set_clientdata(client, NULL);
                kfree(max);
        }
 
index e20330a28959bc539d0691337bf49438e2022efe..65a8ff3e1f8e8d4e1e73a7a7eda4bb9500fb9c82 100644 (file)
@@ -376,7 +376,6 @@ static int wf_sat_remove(struct i2c_client *client)
        /* XXX TODO */
 
        sat->i2c = NULL;
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index 46b3a044eadf41166a60cab6f10153fd1e75f09f..cb20d0b0555adee7c12d5e643a65d142f7f054e0 100644 (file)
@@ -2087,6 +2087,7 @@ static void sync_sbs(mddev_t * mddev, int nospares)
        /* First make sure individual recovery_offsets are correct */
        list_for_each_entry(rdev, &mddev->disks, same_set) {
                if (rdev->raid_disk >= 0 &&
+                   mddev->delta_disks >= 0 &&
                    !test_bit(In_sync, &rdev->flags) &&
                    mddev->curr_resync_completed > rdev->recovery_offset)
                                rdev->recovery_offset = mddev->curr_resync_completed;
@@ -3001,6 +3002,9 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
                return -EINVAL;
        }
 
+       list_for_each_entry(rdev, &mddev->disks, same_set)
+               rdev->new_raid_disk = rdev->raid_disk;
+
        /* ->takeover must set new_* and/or delta_disks
         * if it succeeds, and may set them when it fails.
         */
@@ -3051,13 +3055,35 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
                mddev->safemode = 0;
        }
 
-       module_put(mddev->pers->owner);
-       /* Invalidate devices that are now superfluous */
-       list_for_each_entry(rdev, &mddev->disks, same_set)
-               if (rdev->raid_disk >= mddev->raid_disks) {
-                       rdev->raid_disk = -1;
+       list_for_each_entry(rdev, &mddev->disks, same_set) {
+               char nm[20];
+               if (rdev->raid_disk < 0)
+                       continue;
+               if (rdev->new_raid_disk > mddev->raid_disks)
+                       rdev->new_raid_disk = -1;
+               if (rdev->new_raid_disk == rdev->raid_disk)
+                       continue;
+               sprintf(nm, "rd%d", rdev->raid_disk);
+               sysfs_remove_link(&mddev->kobj, nm);
+       }
+       list_for_each_entry(rdev, &mddev->disks, same_set) {
+               if (rdev->raid_disk < 0)
+                       continue;
+               if (rdev->new_raid_disk == rdev->raid_disk)
+                       continue;
+               rdev->raid_disk = rdev->new_raid_disk;
+               if (rdev->raid_disk < 0)
                        clear_bit(In_sync, &rdev->flags);
+               else {
+                       char nm[20];
+                       sprintf(nm, "rd%d", rdev->raid_disk);
+                       if(sysfs_create_link(&mddev->kobj, &rdev->kobj, nm))
+                               printk("md: cannot register %s for %s after level change\n",
+                                      nm, mdname(mddev));
                }
+       }
+
+       module_put(mddev->pers->owner);
        mddev->pers = pers;
        mddev->private = priv;
        strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
@@ -5895,6 +5921,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
        atomic_inc(&mddev->openers);
        mutex_unlock(&mddev->open_mutex);
 
+       check_disk_size_change(mddev->gendisk, bdev);
  out:
        return err;
 }
@@ -6846,6 +6873,7 @@ void md_do_sync(mddev_t *mddev)
                        rcu_read_lock();
                        list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
                                if (rdev->raid_disk >= 0 &&
+                                   mddev->delta_disks >= 0 &&
                                    !test_bit(Faulty, &rdev->flags) &&
                                    !test_bit(In_sync, &rdev->flags) &&
                                    rdev->recovery_offset < mddev->curr_resync)
index 7ab5ea155452c5b745041e05c155df0ded2dd2c4..10597bfec0001c6ec3d732cab348ba459ee89a1a 100644 (file)
@@ -78,6 +78,9 @@ struct mdk_rdev_s
 
        int desc_nr;                    /* descriptor index in the superblock */
        int raid_disk;                  /* role of device in array */
+       int new_raid_disk;              /* role that the device will have in
+                                        * the array after a level-change completes.
+                                        */
        int saved_raid_disk;            /* role that device used to have in the
                                         * array and could again if we did a partial
                                         * resync from the bitmap
index e70f004c99e8b2bf146de202079f763022a048c2..563abed5a2cb73b68cc86d4230b8e1ab0a510b61 100644 (file)
@@ -173,9 +173,11 @@ static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
        list_for_each_entry(rdev1, &mddev->disks, same_set) {
                int j = rdev1->raid_disk;
 
-               if (mddev->level == 10)
+               if (mddev->level == 10) {
                        /* taking over a raid10-n2 array */
                        j /= 2;
+                       rdev1->new_raid_disk = j;
+               }
 
                if (j < 0 || j >= mddev->raid_disks) {
                        printk(KERN_ERR "md/raid0:%s: bad disk number %d - "
@@ -361,12 +363,6 @@ static int raid0_run(mddev_t *mddev)
                mddev->private = conf;
        }
        conf = mddev->private;
-       if (conf->scale_raid_disks) {
-               int i;
-               for (i=0; i < conf->strip_zone[0].nb_dev; i++)
-                       conf->devlist[i]->raid_disk /= conf->scale_raid_disks;
-               /* FIXME update sysfs rd links */
-       }
 
        /* calculate array device size */
        md_set_array_sectors(mddev, raid0_size(mddev, 0, 0));
@@ -573,7 +569,7 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev)
        return;
 }
 
-static void *raid0_takeover_raid5(mddev_t *mddev)
+static void *raid0_takeover_raid45(mddev_t *mddev)
 {
        mdk_rdev_t *rdev;
        raid0_conf_t *priv_conf;
@@ -596,6 +592,7 @@ static void *raid0_takeover_raid5(mddev_t *mddev)
 
        /* Set new parameters */
        mddev->new_level = 0;
+       mddev->new_layout = 0;
        mddev->new_chunk_sectors = mddev->chunk_sectors;
        mddev->raid_disks--;
        mddev->delta_disks = -1;
@@ -635,6 +632,7 @@ static void *raid0_takeover_raid10(mddev_t *mddev)
 
        /* Set new parameters */
        mddev->new_level = 0;
+       mddev->new_layout = 0;
        mddev->new_chunk_sectors = mddev->chunk_sectors;
        mddev->delta_disks = - mddev->raid_disks / 2;
        mddev->raid_disks += mddev->delta_disks;
@@ -643,19 +641,22 @@ static void *raid0_takeover_raid10(mddev_t *mddev)
        mddev->recovery_cp = MaxSector;
 
        create_strip_zones(mddev, &priv_conf);
-       priv_conf->scale_raid_disks = 2;
        return priv_conf;
 }
 
 static void *raid0_takeover(mddev_t *mddev)
 {
        /* raid0 can take over:
+        *  raid4 - if all data disks are active.
         *  raid5 - providing it is Raid4 layout and one disk is faulty
         *  raid10 - assuming we have all necessary active disks
         */
+       if (mddev->level == 4)
+               return raid0_takeover_raid45(mddev);
+
        if (mddev->level == 5) {
                if (mddev->layout == ALGORITHM_PARITY_N)
-                       return raid0_takeover_raid5(mddev);
+                       return raid0_takeover_raid45(mddev);
 
                printk(KERN_ERR "md/raid0:%s: Raid can only takeover Raid5 with layout: %d\n",
                       mdname(mddev), ALGORITHM_PARITY_N);
index d724e664ca4dace9fa27fee815d84d6b7e40d946..91f8e876ee64516949ddad76b374bc657fd1879c 100644 (file)
@@ -13,9 +13,6 @@ struct raid0_private_data
        struct strip_zone *strip_zone;
        mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
        int nr_strip_zones;
-       int scale_raid_disks; /* divide rdev->raid_disks by this in run()
-                              * to handle conversion from raid10
-                              */
 };
 
 typedef struct raid0_private_data raid0_conf_t;
index 03724992cdf20ea8ed46aaf2aee29ef845f29c54..42e64e4e5e2503fb4b81c12ac6706932f4397ba4 100644 (file)
@@ -1482,14 +1482,14 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
        int sectors = r10_bio->sectors;
        mdk_rdev_t*rdev;
        int max_read_errors = atomic_read(&mddev->max_corr_read_errors);
+       int d = r10_bio->devs[r10_bio->read_slot].devnum;
 
        rcu_read_lock();
-       {
-               int d = r10_bio->devs[r10_bio->read_slot].devnum;
+       rdev = rcu_dereference(conf->mirrors[d].rdev);
+       if (rdev) { /* If rdev is not NULL */
                char b[BDEVNAME_SIZE];
                int cur_read_error_count = 0;
 
-               rdev = rcu_dereference(conf->mirrors[d].rdev);
                bdevname(rdev->bdev, b);
 
                if (test_bit(Faulty, &rdev->flags)) {
@@ -1530,7 +1530,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
 
                rcu_read_lock();
                do {
-                       int d = r10_bio->devs[sl].devnum;
+                       d = r10_bio->devs[sl].devnum;
                        rdev = rcu_dereference(conf->mirrors[d].rdev);
                        if (rdev &&
                            test_bit(In_sync, &rdev->flags)) {
@@ -1564,7 +1564,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
                rcu_read_lock();
                while (sl != r10_bio->read_slot) {
                        char b[BDEVNAME_SIZE];
-                       int d;
+
                        if (sl==0)
                                sl = conf->copies;
                        sl--;
@@ -1601,7 +1601,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
                }
                sl = start;
                while (sl != r10_bio->read_slot) {
-                       int d;
+
                        if (sl==0)
                                sl = conf->copies;
                        sl--;
@@ -2161,22 +2161,22 @@ static conf_t *setup_conf(mddev_t *mddev)
        sector_t stride, size;
        int err = -EINVAL;
 
-       if (mddev->chunk_sectors < (PAGE_SIZE >> 9) ||
-           !is_power_of_2(mddev->chunk_sectors)) {
+       if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) ||
+           !is_power_of_2(mddev->new_chunk_sectors)) {
                printk(KERN_ERR "md/raid10:%s: chunk size must be "
                       "at least PAGE_SIZE(%ld) and be a power of 2.\n",
                       mdname(mddev), PAGE_SIZE);
                goto out;
        }
 
-       nc = mddev->layout & 255;
-       fc = (mddev->layout >> 8) & 255;
-       fo = mddev->layout & (1<<16);
+       nc = mddev->new_layout & 255;
+       fc = (mddev->new_layout >> 8) & 255;
+       fo = mddev->new_layout & (1<<16);
 
        if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
-           (mddev->layout >> 17)) {
+           (mddev->new_layout >> 17)) {
                printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n",
-                      mdname(mddev), mddev->layout);
+                      mdname(mddev), mddev->new_layout);
                goto out;
        }
 
@@ -2241,7 +2241,6 @@ static conf_t *setup_conf(mddev_t *mddev)
        if (!conf->thread)
                goto out;
 
-       conf->scale_disks = 0;
        conf->mddev = mddev;
        return conf;
 
@@ -2300,11 +2299,6 @@ static int run(mddev_t *mddev)
                if (disk_idx >= conf->raid_disks
                    || disk_idx < 0)
                        continue;
-               if (conf->scale_disks) {
-                       disk_idx *= conf->scale_disks;
-                       rdev->raid_disk = disk_idx;
-                       /* MOVE 'rd%d' link !! */
-               }
                disk = conf->mirrors + disk_idx;
 
                disk->rdev = rdev;
@@ -2435,26 +2429,22 @@ static void *raid10_takeover_raid0(mddev_t *mddev)
                return ERR_PTR(-EINVAL);
        }
 
-       /* Update slot numbers to obtain
-        * degraded raid10 with missing mirrors
-        */
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
-               rdev->raid_disk *= 2;
-       }
-
        /* Set new parameters */
        mddev->new_level = 10;
        /* new layout: far_copies = 1, near_copies = 2 */
        mddev->new_layout = (1<<8) + 2;
        mddev->new_chunk_sectors = mddev->chunk_sectors;
        mddev->delta_disks = mddev->raid_disks;
-       mddev->degraded = mddev->raid_disks;
        mddev->raid_disks *= 2;
        /* make sure it will be not marked as dirty */
        mddev->recovery_cp = MaxSector;
 
        conf = setup_conf(mddev);
-       conf->scale_disks = 2;
+       if (!IS_ERR(conf))
+               list_for_each_entry(rdev, &mddev->disks, same_set)
+                       if (rdev->raid_disk >= 0)
+                               rdev->new_raid_disk = rdev->raid_disk * 2;
+               
        return conf;
 }
 
index 3824a087e17c65efe0ee327772f7fa699fb41f22..2316ac2e8e218c6a97c96ebd35d99172e0bcb4fc 100644 (file)
@@ -38,11 +38,6 @@ struct r10_private_data_s {
        int chunk_shift; /* shift from chunks to sectors */
        sector_t chunk_mask;
 
-       int                     scale_disks;  /* When starting array, multiply
-                                              * each ->raid_disk by this.
-                                              * Need for raid0->raid10 migration
-                                              */
-
        struct list_head        retry_list;
        /* queue pending writes and submit them on unplug */
        struct bio_list         pending_bio_list;
index d2c0f94fa37d7a708b1c6854e7be3b1d3b60162f..96c690279fc6b58c7147c5860bf16417baa2149e 100644 (file)
@@ -277,12 +277,13 @@ out:
        return sh;
 }
 
-static void shrink_buffers(struct stripe_head *sh, int num)
+static void shrink_buffers(struct stripe_head *sh)
 {
        struct page *p;
        int i;
+       int num = sh->raid_conf->pool_size;
 
-       for (i=0; i<num ; i++) {
+       for (i = 0; i < num ; i++) {
                p = sh->dev[i].page;
                if (!p)
                        continue;
@@ -291,11 +292,12 @@ static void shrink_buffers(struct stripe_head *sh, int num)
        }
 }
 
-static int grow_buffers(struct stripe_head *sh, int num)
+static int grow_buffers(struct stripe_head *sh)
 {
        int i;
+       int num = sh->raid_conf->pool_size;
 
-       for (i=0; i<num; i++) {
+       for (i = 0; i < num; i++) {
                struct page *page;
 
                if (!(page = alloc_page(GFP_KERNEL))) {
@@ -364,6 +366,73 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector,
        return NULL;
 }
 
+/*
+ * Need to check if array has failed when deciding whether to:
+ *  - start an array
+ *  - remove non-faulty devices
+ *  - add a spare
+ *  - allow a reshape
+ * This determination is simple when no reshape is happening.
+ * However if there is a reshape, we need to carefully check
+ * both the before and after sections.
+ * This is because some failed devices may only affect one
+ * of the two sections, and some non-in_sync devices may
+ * be insync in the section most affected by failed devices.
+ */
+static int has_failed(raid5_conf_t *conf)
+{
+       int degraded;
+       int i;
+       if (conf->mddev->reshape_position == MaxSector)
+               return conf->mddev->degraded > conf->max_degraded;
+
+       rcu_read_lock();
+       degraded = 0;
+       for (i = 0; i < conf->previous_raid_disks; i++) {
+               mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+               if (!rdev || test_bit(Faulty, &rdev->flags))
+                       degraded++;
+               else if (test_bit(In_sync, &rdev->flags))
+                       ;
+               else
+                       /* not in-sync or faulty.
+                        * If the reshape increases the number of devices,
+                        * this is being recovered by the reshape, so
+                        * this 'previous' section is not in_sync.
+                        * If the number of devices is being reduced however,
+                        * the device can only be part of the array if
+                        * we are reverting a reshape, so this section will
+                        * be in-sync.
+                        */
+                       if (conf->raid_disks >= conf->previous_raid_disks)
+                               degraded++;
+       }
+       rcu_read_unlock();
+       if (degraded > conf->max_degraded)
+               return 1;
+       rcu_read_lock();
+       degraded = 0;
+       for (i = 0; i < conf->raid_disks; i++) {
+               mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+               if (!rdev || test_bit(Faulty, &rdev->flags))
+                       degraded++;
+               else if (test_bit(In_sync, &rdev->flags))
+                       ;
+               else
+                       /* not in-sync or faulty.
+                        * If reshape increases the number of devices, this
+                        * section has already been recovered, else it
+                        * almost certainly hasn't.
+                        */
+                       if (conf->raid_disks <= conf->previous_raid_disks)
+                               degraded++;
+       }
+       rcu_read_unlock();
+       if (degraded > conf->max_degraded)
+               return 1;
+       return 0;
+}
+
 static void unplug_slaves(mddev_t *mddev);
 static void raid5_unplug_device(struct request_queue *q);
 
@@ -1240,19 +1309,18 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
 static int grow_one_stripe(raid5_conf_t *conf)
 {
        struct stripe_head *sh;
-       int disks = max(conf->raid_disks, conf->previous_raid_disks);
        sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
        if (!sh)
                return 0;
-       memset(sh, 0, sizeof(*sh) + (disks-1)*sizeof(struct r5dev));
+       memset(sh, 0, sizeof(*sh) + (conf->pool_size-1)*sizeof(struct r5dev));
        sh->raid_conf = conf;
        spin_lock_init(&sh->lock);
        #ifdef CONFIG_MULTICORE_RAID456
        init_waitqueue_head(&sh->ops.wait_for_ops);
        #endif
 
-       if (grow_buffers(sh, disks)) {
-               shrink_buffers(sh, disks);
+       if (grow_buffers(sh)) {
+               shrink_buffers(sh);
                kmem_cache_free(conf->slab_cache, sh);
                return 0;
        }
@@ -1468,7 +1536,7 @@ static int drop_one_stripe(raid5_conf_t *conf)
        if (!sh)
                return 0;
        BUG_ON(atomic_read(&sh->count));
-       shrink_buffers(sh, conf->pool_size);
+       shrink_buffers(sh);
        kmem_cache_free(conf->slab_cache, sh);
        atomic_dec(&conf->active_stripes);
        return 1;
@@ -2963,7 +3031,6 @@ static void handle_stripe5(struct stripe_head *sh)
                mdk_rdev_t *rdev;
 
                dev = &sh->dev[i];
-               clear_bit(R5_Insync, &dev->flags);
 
                pr_debug("check %d: state 0x%lx toread %p read %p write %p "
                        "written %p\n", i, dev->flags, dev->toread, dev->read,
@@ -3000,17 +3067,27 @@ static void handle_stripe5(struct stripe_head *sh)
                        blocked_rdev = rdev;
                        atomic_inc(&rdev->nr_pending);
                }
-               if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+               clear_bit(R5_Insync, &dev->flags);
+               if (!rdev)
+                       /* Not in-sync */;
+               else if (test_bit(In_sync, &rdev->flags))
+                       set_bit(R5_Insync, &dev->flags);
+               else {
+                       /* could be in-sync depending on recovery/reshape status */
+                       if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
+                               set_bit(R5_Insync, &dev->flags);
+               }
+               if (!test_bit(R5_Insync, &dev->flags)) {
                        /* The ReadError flag will just be confusing now */
                        clear_bit(R5_ReadError, &dev->flags);
                        clear_bit(R5_ReWrite, &dev->flags);
                }
-               if (!rdev || !test_bit(In_sync, &rdev->flags)
-                   || test_bit(R5_ReadError, &dev->flags)) {
+               if (test_bit(R5_ReadError, &dev->flags))
+                       clear_bit(R5_Insync, &dev->flags);
+               if (!test_bit(R5_Insync, &dev->flags)) {
                        s.failed++;
                        s.failed_num = i;
-               } else
-                       set_bit(R5_Insync, &dev->flags);
+               }
        }
        rcu_read_unlock();
 
@@ -3244,7 +3321,6 @@ static void handle_stripe6(struct stripe_head *sh)
        for (i=disks; i--; ) {
                mdk_rdev_t *rdev;
                dev = &sh->dev[i];
-               clear_bit(R5_Insync, &dev->flags);
 
                pr_debug("check %d: state 0x%lx read %p write %p written %p\n",
                        i, dev->flags, dev->toread, dev->towrite, dev->written);
@@ -3282,18 +3358,28 @@ static void handle_stripe6(struct stripe_head *sh)
                        blocked_rdev = rdev;
                        atomic_inc(&rdev->nr_pending);
                }
-               if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+               clear_bit(R5_Insync, &dev->flags);
+               if (!rdev)
+                       /* Not in-sync */;
+               else if (test_bit(In_sync, &rdev->flags))
+                       set_bit(R5_Insync, &dev->flags);
+               else {
+                       /* in sync if before recovery_offset */
+                       if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
+                               set_bit(R5_Insync, &dev->flags);
+               }
+               if (!test_bit(R5_Insync, &dev->flags)) {
                        /* The ReadError flag will just be confusing now */
                        clear_bit(R5_ReadError, &dev->flags);
                        clear_bit(R5_ReWrite, &dev->flags);
                }
-               if (!rdev || !test_bit(In_sync, &rdev->flags)
-                   || test_bit(R5_ReadError, &dev->flags)) {
+               if (test_bit(R5_ReadError, &dev->flags))
+                       clear_bit(R5_Insync, &dev->flags);
+               if (!test_bit(R5_Insync, &dev->flags)) {
                        if (s.failed < 2)
                                r6s.failed_num[s.failed] = i;
                        s.failed++;
-               } else
-                       set_bit(R5_Insync, &dev->flags);
+               }
        }
        rcu_read_unlock();
 
@@ -4971,8 +5057,10 @@ static int run(mddev_t *mddev)
        list_for_each_entry(rdev, &mddev->disks, same_set) {
                if (rdev->raid_disk < 0)
                        continue;
-               if (test_bit(In_sync, &rdev->flags))
+               if (test_bit(In_sync, &rdev->flags)) {
                        working_disks++;
+                       continue;
+               }
                /* This disc is not fully in-sync.  However if it
                 * just stored parity (beyond the recovery_offset),
                 * when we don't need to be concerned about the
@@ -5005,7 +5093,7 @@ static int run(mddev_t *mddev)
        mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks)
                           - working_disks);
 
-       if (mddev->degraded > conf->max_degraded) {
+       if (has_failed(conf)) {
                printk(KERN_ERR "md/raid:%s: not enough operational devices"
                        " (%d/%d failed)\n",
                        mdname(mddev), mddev->degraded, conf->raid_disks);
@@ -5207,6 +5295,7 @@ static int raid5_spare_active(mddev_t *mddev)
        for (i = 0; i < conf->raid_disks; i++) {
                tmp = conf->disks + i;
                if (tmp->rdev
+                   && tmp->rdev->recovery_offset == MaxSector
                    && !test_bit(Faulty, &tmp->rdev->flags)
                    && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
                        unsigned long flags;
@@ -5242,7 +5331,7 @@ static int raid5_remove_disk(mddev_t *mddev, int number)
                 * isn't possible.
                 */
                if (!test_bit(Faulty, &rdev->flags) &&
-                   mddev->degraded <= conf->max_degraded &&
+                   !has_failed(conf) &&
                    number < conf->raid_disks) {
                        err = -EBUSY;
                        goto abort;
@@ -5270,7 +5359,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
        int first = 0;
        int last = conf->raid_disks - 1;
 
-       if (mddev->degraded > conf->max_degraded)
+       if (has_failed(conf))
                /* no point adding a device */
                return -EINVAL;
 
@@ -5362,7 +5451,7 @@ static int check_reshape(mddev_t *mddev)
        if (mddev->bitmap)
                /* Cannot grow a bitmap yet */
                return -EBUSY;
-       if (mddev->degraded > conf->max_degraded)
+       if (has_failed(conf))
                return -EINVAL;
        if (mddev->delta_disks < 0) {
                /* We might be able to shrink, but the devices must
@@ -5437,8 +5526,13 @@ static int raid5_start_reshape(mddev_t *mddev)
 
        /* Add some new drives, as many as will fit.
         * We know there are enough to make the newly sized array work.
+        * Don't add devices if we are reducing the number of
+        * devices in the array.  This is because it is not possible
+        * to correctly record the "partially reconstructed" state of
+        * such devices during the reshape and confusion could result.
         */
-       list_for_each_entry(rdev, &mddev->disks, same_set)
+       if (mddev->delta_disks >= 0)
+           list_for_each_entry(rdev, &mddev->disks, same_set)
                if (rdev->raid_disk < 0 &&
                    !test_bit(Faulty, &rdev->flags)) {
                        if (raid5_add_disk(mddev, rdev) == 0) {
@@ -5460,7 +5554,7 @@ static int raid5_start_reshape(mddev_t *mddev)
                }
 
        /* When a reshape changes the number of devices, ->degraded
-        * is measured against the large of the pre and post number of
+        * is measured against the larger of the pre and post number of
         * devices.*/
        if (mddev->delta_disks > 0) {
                spin_lock_irqsave(&conf->device_lock, flags);
index 195c6cf359f67fbb166f270ba5643e6b3c9be7d5..d22a8ec523fc1df4f1b7bc57c7e10c378e0f9956 100644 (file)
@@ -13,6 +13,7 @@ source "drivers/media/IR/keymaps/Kconfig"
 config IR_NEC_DECODER
        tristate "Enable IR raw decoder for the NEC protocol"
        depends on IR_CORE
+       select BITREVERSE
        default y
 
        ---help---
@@ -22,6 +23,7 @@ config IR_NEC_DECODER
 config IR_RC5_DECODER
        tristate "Enable IR raw decoder for the RC-5 protocol"
        depends on IR_CORE
+       select BITREVERSE
        default y
 
        ---help---
index 5e2045670004bbc0fd31f7182740fbf8b3997054..4bbd45f4284c37b53c1169b95f250a1eaf44d01b 100644 (file)
@@ -94,6 +94,7 @@ struct imon_context {
 
        bool display_supported;         /* not all controllers do */
        bool display_isopen;            /* display port has been opened */
+       bool rf_device;                 /* true if iMON 2.4G LT/DT RF device */
        bool rf_isassociating;          /* RF remote associating */
        bool dev_present_intf0;         /* USB device presence, interface 0 */
        bool dev_present_intf1;         /* USB device presence, interface 1 */
@@ -385,7 +386,7 @@ static int display_open(struct inode *inode, struct file *file)
                err("%s: display port is already open", __func__);
                retval = -EBUSY;
        } else {
-               ictx->display_isopen = 1;
+               ictx->display_isopen = true;
                file->private_data = ictx;
                dev_dbg(ictx->dev, "display port opened\n");
        }
@@ -422,7 +423,7 @@ static int display_close(struct inode *inode, struct file *file)
                err("%s: display is not open", __func__);
                retval = -EIO;
        } else {
-               ictx->display_isopen = 0;
+               ictx->display_isopen = false;
                dev_dbg(ictx->dev, "display port closed\n");
                if (!ictx->dev_present_intf0) {
                        /*
@@ -491,12 +492,12 @@ static int send_packet(struct imon_context *ictx)
        }
 
        init_completion(&ictx->tx.finished);
-       ictx->tx.busy = 1;
+       ictx->tx.busy = true;
        smp_rmb(); /* ensure later readers know we're busy */
 
        retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL);
        if (retval) {
-               ictx->tx.busy = 0;
+               ictx->tx.busy = false;
                smp_rmb(); /* ensure later readers know we're not busy */
                err("%s: error submitting urb(%d)", __func__, retval);
        } else {
@@ -682,7 +683,7 @@ static ssize_t store_associate_remote(struct device *d,
                return -ENODEV;
 
        mutex_lock(&ictx->lock);
-       ictx->rf_isassociating = 1;
+       ictx->rf_isassociating = true;
        send_associate_24g(ictx);
        mutex_unlock(&ictx->lock);
 
@@ -950,7 +951,7 @@ static void usb_tx_callback(struct urb *urb)
        ictx->tx.status = urb->status;
 
        /* notify waiters that write has finished */
-       ictx->tx.busy = 0;
+       ictx->tx.busy = false;
        smp_rmb(); /* ensure later readers know we're not busy */
        complete(&ictx->tx.finished);
 }
@@ -1215,7 +1216,7 @@ static bool imon_mouse_event(struct imon_context *ictx,
 {
        char rel_x = 0x00, rel_y = 0x00;
        u8 right_shift = 1;
-       bool mouse_input = 1;
+       bool mouse_input = true;
        int dir = 0;
 
        /* newer iMON device PAD or mouse button */
@@ -1246,7 +1247,7 @@ static bool imon_mouse_event(struct imon_context *ictx,
        } else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) {
                dir = -1;
        } else
-               mouse_input = 0;
+               mouse_input = false;
 
        if (mouse_input) {
                dev_dbg(ictx->dev, "sending mouse data via input subsystem\n");
@@ -1450,7 +1451,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
        unsigned char *buf = urb->transfer_buffer;
        struct device *dev = ictx->dev;
        u32 kc;
-       bool norelease = 0;
+       bool norelease = false;
        int i;
        u64 temp_key;
        u64 panel_key = 0;
@@ -1465,7 +1466,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
        idev = ictx->idev;
 
        /* filter out junk data on the older 0xffdc imon devices */
-       if ((buf[0] == 0xff) && (buf[7] == 0xff))
+       if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff))
                return;
 
        /* Figure out what key was pressed */
@@ -1517,7 +1518,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
             !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) {
                len = 8;
                imon_pad_to_keys(ictx, buf);
-               norelease = 1;
+               norelease = true;
        }
 
        if (debug) {
@@ -1580,7 +1581,7 @@ not_input_data:
            (buf[6] == 0x5E && buf[7] == 0xDF))) {      /* DT */
                dev_warn(dev, "%s: remote associated refid=%02X\n",
                         __func__, buf[1]);
-               ictx->rf_isassociating = 0;
+               ictx->rf_isassociating = false;
        }
 }
 
@@ -1790,9 +1791,9 @@ static bool imon_find_endpoints(struct imon_context *ictx,
        int ifnum = iface_desc->desc.bInterfaceNumber;
        int num_endpts = iface_desc->desc.bNumEndpoints;
        int i, ep_dir, ep_type;
-       bool ir_ep_found = 0;
-       bool display_ep_found = 0;
-       bool tx_control = 0;
+       bool ir_ep_found = false;
+       bool display_ep_found = false;
+       bool tx_control = false;
 
        /*
         * Scan the endpoint list and set:
@@ -1808,13 +1809,13 @@ static bool imon_find_endpoints(struct imon_context *ictx,
                    ep_type == USB_ENDPOINT_XFER_INT) {
 
                        rx_endpoint = ep;
-                       ir_ep_found = 1;
+                       ir_ep_found = true;
                        dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__);
 
                } else if (!display_ep_found && ep_dir == USB_DIR_OUT &&
                           ep_type == USB_ENDPOINT_XFER_INT) {
                        tx_endpoint = ep;
-                       display_ep_found = 1;
+                       display_ep_found = true;
                        dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__);
                }
        }
@@ -1835,8 +1836,8 @@ static bool imon_find_endpoints(struct imon_context *ictx,
         * newer iMON devices that use control urb instead of interrupt
         */
        if (!display_ep_found) {
-               tx_control = 1;
-               display_ep_found = 1;
+               tx_control = true;
+               display_ep_found = true;
                dev_dbg(ictx->dev, "%s: device uses control endpoint, not "
                        "interface OUT endpoint\n", __func__);
        }
@@ -1847,7 +1848,7 @@ static bool imon_find_endpoints(struct imon_context *ictx,
         * and without... :\
         */
        if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) {
-               display_ep_found = 0;
+               display_ep_found = false;
                dev_dbg(ictx->dev, "%s: device has no display\n", __func__);
        }
 
@@ -1856,7 +1857,7 @@ static bool imon_find_endpoints(struct imon_context *ictx,
         * that refers to e.g. /dev/lcd0 (a character device LCD or VFD).
         */
        if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
-               display_ep_found = 0;
+               display_ep_found = false;
                dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__);
        }
 
@@ -1905,9 +1906,10 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
 
        ictx->dev = dev;
        ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf));
-       ictx->dev_present_intf0 = 1;
+       ictx->dev_present_intf0 = true;
        ictx->rx_urb_intf0 = rx_urb;
        ictx->tx_urb = tx_urb;
+       ictx->rf_device = false;
 
        ictx->vendor  = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor);
        ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct);
@@ -1979,7 +1981,7 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf,
        }
 
        ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf));
-       ictx->dev_present_intf1 = 1;
+       ictx->dev_present_intf1 = true;
        ictx->rx_urb_intf1 = rx_urb;
 
        ret = -ENODEV;
@@ -2047,6 +2049,12 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
                dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR");
                ictx->display_supported = false;
                break;
+       /* iMON 2.4G LT (usb stick), no display, iMON RF */
+       case 0x4e:
+               dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF");
+               ictx->display_supported = false;
+               ictx->rf_device = true;
+               break;
        /* iMON VFD, no IR (does have vol knob tho) */
        case 0x35:
                dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
@@ -2197,15 +2205,6 @@ static int __devinit imon_probe(struct usb_interface *interface,
                        goto fail;
                }
 
-               if (product == 0xffdc) {
-                       /* RF products *also* use 0xffdc... sigh... */
-                       sysfs_err = sysfs_create_group(&interface->dev.kobj,
-                                                      &imon_rf_attribute_group);
-                       if (sysfs_err)
-                               err("%s: Could not create RF sysfs entries(%d)",
-                                   __func__, sysfs_err);
-               }
-
        } else {
        /* this is the secondary interface on the device */
                ictx = imon_init_intf1(interface, first_if_ctx);
@@ -2233,6 +2232,14 @@ static int __devinit imon_probe(struct usb_interface *interface,
 
                imon_set_display_type(ictx, interface);
 
+               if (product == 0xffdc && ictx->rf_device) {
+                       sysfs_err = sysfs_create_group(&interface->dev.kobj,
+                                                      &imon_rf_attribute_group);
+                       if (sysfs_err)
+                               err("%s: Could not create RF sysfs entries(%d)",
+                                   __func__, sysfs_err);
+               }
+
                if (ictx->display_supported)
                        imon_init_display(ictx, interface);
        }
@@ -2297,7 +2304,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
        }
 
        if (ifnum == 0) {
-               ictx->dev_present_intf0 = 0;
+               ictx->dev_present_intf0 = false;
                usb_kill_urb(ictx->rx_urb_intf0);
                input_unregister_device(ictx->idev);
                if (ictx->display_supported) {
@@ -2307,7 +2314,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
                                usb_deregister_dev(interface, &imon_vfd_class);
                }
        } else {
-               ictx->dev_present_intf1 = 0;
+               ictx->dev_present_intf1 = false;
                usb_kill_urb(ictx->rx_urb_intf1);
                if (ictx->display_type == IMON_DISPLAY_TYPE_VGA)
                        input_unregister_device(ictx->touch);
index 9374a006f43d6c82ba276e3d35f8261aa16a4108..94a8577e72ebd3ba09e264d2abd2213a0ead42c8 100644 (file)
@@ -490,11 +490,12 @@ int __ir_input_register(struct input_dev *input_dev,
        if (rc < 0)
                goto out_table;
 
-       if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) {
-               rc = ir_raw_event_register(input_dev);
-               if (rc < 0)
-                       goto out_event;
-       }
+       if (ir_dev->props)
+               if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) {
+                       rc = ir_raw_event_register(input_dev);
+                       if (rc < 0)
+                               goto out_event;
+               }
 
        IR_dprintk(1, "Registered input device on %s for %s remote.\n",
                   driver_name, rc_tab->name);
@@ -530,8 +531,10 @@ void ir_input_unregister(struct input_dev *input_dev)
        IR_dprintk(1, "Freed keycode table\n");
 
        del_timer_sync(&ir_dev->timer_keyup);
-       if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
-               ir_raw_event_unregister(input_dev);
+       if (ir_dev->props)
+               if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
+                       ir_raw_event_unregister(input_dev);
+
        rc_tab = &ir_dev->rc_tab;
        rc_tab->size = 0;
        kfree(rc_tab->scan);
index d7da63e16c92eff8fa4d37db0af99b544fa24eb1..2098dd1488e00647245057653ef6c1decb514026 100644 (file)
@@ -221,9 +221,10 @@ int ir_register_class(struct input_dev *input_dev)
        if (unlikely(devno < 0))
                return devno;
 
-       if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
-               ir_dev->dev.type = &rc_dev_type;
-       else
+       if (ir_dev->props) {
+               if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
+                       ir_dev->dev.type = &rc_dev_type;
+       } else
                ir_dev->dev.type = &ir_raw_dev_type;
 
        ir_dev->dev.class = &ir_input_class;
index ec25258a955f73b7f5fdbdd1709b435c31405c1f..aea649fbcf5a6a929a88dc7979f7840817b155c8 100644 (file)
@@ -6,7 +6,8 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
                        rc-avermedia.o \
                        rc-avermedia-cardbus.o \
                        rc-avermedia-dvbt.o \
-                       rc-avermedia-m135a-rm-jx.o \
+                       rc-avermedia-m135a.o \
+                       rc-avermedia-m733a-rm-k6.o \
                        rc-avertv-303.o \
                        rc-behold.o \
                        rc-behold-columbus.o \
diff --git a/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c b/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c
deleted file mode 100644 (file)
index 101e7ea..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/* avermedia-m135a-rm-jx.h - Keytable for avermedia_m135a_rm_jx Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <media/rc-map.h>
-
-/*
- * Avermedia M135A with IR model RM-JX
- * The same codes exist on both Positivo (BR) and original IR
- * Mauro Carvalho Chehab <mchehab@infradead.org>
- */
-
-static struct ir_scancode avermedia_m135a_rm_jx[] = {
-       { 0x0200, KEY_POWER2 },
-       { 0x022e, KEY_DOT },            /* '.' */
-       { 0x0201, KEY_MODE },           /* TV/FM or SOURCE */
-
-       { 0x0205, KEY_1 },
-       { 0x0206, KEY_2 },
-       { 0x0207, KEY_3 },
-       { 0x0209, KEY_4 },
-       { 0x020a, KEY_5 },
-       { 0x020b, KEY_6 },
-       { 0x020d, KEY_7 },
-       { 0x020e, KEY_8 },
-       { 0x020f, KEY_9 },
-       { 0x0211, KEY_0 },
-
-       { 0x0213, KEY_RIGHT },          /* -> or L */
-       { 0x0212, KEY_LEFT },           /* <- or R */
-
-       { 0x0217, KEY_SLEEP },          /* Capturar Imagem or Snapshot */
-       { 0x0210, KEY_SHUFFLE },        /* Amostra or 16 chan prev */
-
-       { 0x0303, KEY_CHANNELUP },
-       { 0x0302, KEY_CHANNELDOWN },
-       { 0x021f, KEY_VOLUMEUP },
-       { 0x021e, KEY_VOLUMEDOWN },
-       { 0x020c, KEY_ENTER },          /* Full Screen */
-
-       { 0x0214, KEY_MUTE },
-       { 0x0208, KEY_AUDIO },
-
-       { 0x0203, KEY_TEXT },           /* Teletext */
-       { 0x0204, KEY_EPG },
-       { 0x022b, KEY_TV2 },            /* TV2 or PIP */
-
-       { 0x021d, KEY_RED },
-       { 0x021c, KEY_YELLOW },
-       { 0x0301, KEY_GREEN },
-       { 0x0300, KEY_BLUE },
-
-       { 0x021a, KEY_PLAYPAUSE },
-       { 0x0219, KEY_RECORD },
-       { 0x0218, KEY_PLAY },
-       { 0x021b, KEY_STOP },
-};
-
-static struct rc_keymap avermedia_m135a_rm_jx_map = {
-       .map = {
-               .scan    = avermedia_m135a_rm_jx,
-               .size    = ARRAY_SIZE(avermedia_m135a_rm_jx),
-               .ir_type = IR_TYPE_NEC,
-               .name    = RC_MAP_AVERMEDIA_M135A_RM_JX,
-       }
-};
-
-static int __init init_rc_map_avermedia_m135a_rm_jx(void)
-{
-       return ir_register_map(&avermedia_m135a_rm_jx_map);
-}
-
-static void __exit exit_rc_map_avermedia_m135a_rm_jx(void)
-{
-       ir_unregister_map(&avermedia_m135a_rm_jx_map);
-}
-
-module_init(init_rc_map_avermedia_m135a_rm_jx)
-module_exit(exit_rc_map_avermedia_m135a_rm_jx)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/IR/keymaps/rc-avermedia-m135a.c b/drivers/media/IR/keymaps/rc-avermedia-m135a.c
new file mode 100644 (file)
index 0000000..e4471fb
--- /dev/null
@@ -0,0 +1,147 @@
+/* avermedia-m135a.c - Keytable for Avermedia M135A Remote Controllers
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <media/rc-map.h>
+
+/*
+ * Avermedia M135A with RM-JX and RM-K6 remote controls
+ *
+ * On Avermedia M135A with IR model RM-JX, the same codes exist on both
+ * Positivo (BR) and original IR, initial version and remote control codes
+ * added by Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * Positivo also ships Avermedia M135A with model RM-K6, extra control
+ * codes added by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ */
+
+static struct ir_scancode avermedia_m135a[] = {
+       /* RM-JX */
+       { 0x0200, KEY_POWER2 },
+       { 0x022e, KEY_DOT },            /* '.' */
+       { 0x0201, KEY_MODE },           /* TV/FM or SOURCE */
+
+       { 0x0205, KEY_1 },
+       { 0x0206, KEY_2 },
+       { 0x0207, KEY_3 },
+       { 0x0209, KEY_4 },
+       { 0x020a, KEY_5 },
+       { 0x020b, KEY_6 },
+       { 0x020d, KEY_7 },
+       { 0x020e, KEY_8 },
+       { 0x020f, KEY_9 },
+       { 0x0211, KEY_0 },
+
+       { 0x0213, KEY_RIGHT },          /* -> or L */
+       { 0x0212, KEY_LEFT },           /* <- or R */
+
+       { 0x0217, KEY_SLEEP },          /* Capturar Imagem or Snapshot */
+       { 0x0210, KEY_SHUFFLE },        /* Amostra or 16 chan prev */
+
+       { 0x0303, KEY_CHANNELUP },
+       { 0x0302, KEY_CHANNELDOWN },
+       { 0x021f, KEY_VOLUMEUP },
+       { 0x021e, KEY_VOLUMEDOWN },
+       { 0x020c, KEY_ENTER },          /* Full Screen */
+
+       { 0x0214, KEY_MUTE },
+       { 0x0208, KEY_AUDIO },
+
+       { 0x0203, KEY_TEXT },           /* Teletext */
+       { 0x0204, KEY_EPG },
+       { 0x022b, KEY_TV2 },            /* TV2 or PIP */
+
+       { 0x021d, KEY_RED },
+       { 0x021c, KEY_YELLOW },
+       { 0x0301, KEY_GREEN },
+       { 0x0300, KEY_BLUE },
+
+       { 0x021a, KEY_PLAYPAUSE },
+       { 0x0219, KEY_RECORD },
+       { 0x0218, KEY_PLAY },
+       { 0x021b, KEY_STOP },
+
+       /* RM-K6 */
+       { 0x0401, KEY_POWER2 },
+       { 0x0406, KEY_MUTE },
+       { 0x0408, KEY_MODE },     /* TV/FM */
+
+       { 0x0409, KEY_1 },
+       { 0x040a, KEY_2 },
+       { 0x040b, KEY_3 },
+       { 0x040c, KEY_4 },
+       { 0x040d, KEY_5 },
+       { 0x040e, KEY_6 },
+       { 0x040f, KEY_7 },
+       { 0x0410, KEY_8 },
+       { 0x0411, KEY_9 },
+       { 0x044c, KEY_DOT },      /* '.' */
+       { 0x0412, KEY_0 },
+       { 0x0407, KEY_REFRESH },  /* Refresh/Reload */
+
+       { 0x0413, KEY_AUDIO },
+       { 0x0440, KEY_SCREEN },   /* Full Screen toggle */
+       { 0x0441, KEY_HOME },
+       { 0x0442, KEY_BACK },
+       { 0x0447, KEY_UP },
+       { 0x0448, KEY_DOWN },
+       { 0x0449, KEY_LEFT },
+       { 0x044a, KEY_RIGHT },
+       { 0x044b, KEY_OK },
+       { 0x0404, KEY_VOLUMEUP },
+       { 0x0405, KEY_VOLUMEDOWN },
+       { 0x0402, KEY_CHANNELUP },
+       { 0x0403, KEY_CHANNELDOWN },
+
+       { 0x0443, KEY_RED },
+       { 0x0444, KEY_GREEN },
+       { 0x0445, KEY_YELLOW },
+       { 0x0446, KEY_BLUE },
+
+       { 0x0414, KEY_TEXT },
+       { 0x0415, KEY_EPG },
+       { 0x041a, KEY_TV2 },      /* PIP */
+       { 0x041b, KEY_MHP },      /* Snapshot */
+
+       { 0x0417, KEY_RECORD },
+       { 0x0416, KEY_PLAYPAUSE },
+       { 0x0418, KEY_STOP },
+       { 0x0419, KEY_PAUSE },
+
+       { 0x041f, KEY_PREVIOUS },
+       { 0x041c, KEY_REWIND },
+       { 0x041d, KEY_FORWARD },
+       { 0x041e, KEY_NEXT },
+};
+
+static struct rc_keymap avermedia_m135a_map = {
+       .map = {
+               .scan    = avermedia_m135a,
+               .size    = ARRAY_SIZE(avermedia_m135a),
+               .ir_type = IR_TYPE_NEC,
+               .name    = RC_MAP_AVERMEDIA_M135A,
+       }
+};
+
+static int __init init_rc_map_avermedia_m135a(void)
+{
+       return ir_register_map(&avermedia_m135a_map);
+}
+
+static void __exit exit_rc_map_avermedia_m135a(void)
+{
+       ir_unregister_map(&avermedia_m135a_map);
+}
+
+module_init(init_rc_map_avermedia_m135a)
+module_exit(exit_rc_map_avermedia_m135a)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c
new file mode 100644 (file)
index 0000000..cf8d457
--- /dev/null
@@ -0,0 +1,95 @@
+/* avermedia-m733a-rm-k6.h - Keytable for avermedia_m733a_rm_k6 Remote Controller
+ *
+ * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <media/rc-map.h>
+
+/*
+ * Avermedia M733A with IR model RM-K6
+ * This is the stock remote controller used with Positivo machines with M733A
+ * Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ */
+
+static struct ir_scancode avermedia_m733a_rm_k6[] = {
+       { 0x0401, KEY_POWER2 },
+       { 0x0406, KEY_MUTE },
+       { 0x0408, KEY_MODE },     /* TV/FM */
+
+       { 0x0409, KEY_1 },
+       { 0x040a, KEY_2 },
+       { 0x040b, KEY_3 },
+       { 0x040c, KEY_4 },
+       { 0x040d, KEY_5 },
+       { 0x040e, KEY_6 },
+       { 0x040f, KEY_7 },
+       { 0x0410, KEY_8 },
+       { 0x0411, KEY_9 },
+       { 0x044c, KEY_DOT },      /* '.' */
+       { 0x0412, KEY_0 },
+       { 0x0407, KEY_REFRESH },  /* Refresh/Reload */
+
+       { 0x0413, KEY_AUDIO },
+       { 0x0440, KEY_SCREEN },   /* Full Screen toggle */
+       { 0x0441, KEY_HOME },
+       { 0x0442, KEY_BACK },
+       { 0x0447, KEY_UP },
+       { 0x0448, KEY_DOWN },
+       { 0x0449, KEY_LEFT },
+       { 0x044a, KEY_RIGHT },
+       { 0x044b, KEY_OK },
+       { 0x0404, KEY_VOLUMEUP },
+       { 0x0405, KEY_VOLUMEDOWN },
+       { 0x0402, KEY_CHANNELUP },
+       { 0x0403, KEY_CHANNELDOWN },
+
+       { 0x0443, KEY_RED },
+       { 0x0444, KEY_GREEN },
+       { 0x0445, KEY_YELLOW },
+       { 0x0446, KEY_BLUE },
+
+       { 0x0414, KEY_TEXT },
+       { 0x0415, KEY_EPG },
+       { 0x041a, KEY_TV2 },      /* PIP */
+       { 0x041b, KEY_MHP },      /* Snapshot */
+
+       { 0x0417, KEY_RECORD },
+       { 0x0416, KEY_PLAYPAUSE },
+       { 0x0418, KEY_STOP },
+       { 0x0419, KEY_PAUSE },
+
+       { 0x041f, KEY_PREVIOUS },
+       { 0x041c, KEY_REWIND },
+       { 0x041d, KEY_FORWARD },
+       { 0x041e, KEY_NEXT },
+};
+
+static struct rc_keymap avermedia_m733a_rm_k6_map = {
+       .map = {
+               .scan    = avermedia_m733a_rm_k6,
+               .size    = ARRAY_SIZE(avermedia_m733a_rm_k6),
+               .ir_type = IR_TYPE_NEC,
+               .name    = RC_MAP_AVERMEDIA_M733A_RM_K6,
+       }
+};
+
+static int __init init_rc_map_avermedia_m733a_rm_k6(void)
+{
+       return ir_register_map(&avermedia_m733a_rm_k6_map);
+}
+
+static void __exit exit_rc_map_avermedia_m733a_rm_k6(void)
+{
+       ir_unregister_map(&avermedia_m733a_rm_k6_map);
+}
+
+module_init(init_rc_map_avermedia_m733a_rm_k6)
+module_exit(exit_rc_map_avermedia_m733a_rm_k6)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
index b762e561a6d58a4de3509fca73989cbdb9bacb4e..bca07c0bcd01e4b872bd02a364bc760fd38735d5 100644 (file)
@@ -594,7 +594,7 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id)
 int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
 {
        struct input_dev *input_dev;
-       char *ir_codes = NULL;
+       char *ir_codes = RC_MAP_DM1105_NEC;
        int err = -ENOMEM;
 
        input_dev = input_allocate_device();
index f6dac2bb0ac658c2f14fa39d65644ecb117d3547..6c3a8a06ccab03ed30fcf4481958a1d532f7fbcf 100644 (file)
@@ -351,6 +351,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
        const u8 *ts, *ts_end, *from_where = NULL;
        u8 ts_remain = 0, how_much = 0, new_ts = 1;
        struct ethhdr *ethh = NULL;
+       bool error = false;
 
 #ifdef ULE_DEBUG
        /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */
@@ -460,10 +461,16 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 
                                                /* Drop partly decoded SNDU, reset state, resync on PUSI. */
                                                if (priv->ule_skb) {
-                                                       dev_kfree_skb( priv->ule_skb );
+                                                       error = true;
+                                                       dev_kfree_skb(priv->ule_skb);
+                                               }
+
+                                               if (error || priv->ule_sndu_remain) {
                                                        dev->stats.rx_errors++;
                                                        dev->stats.rx_frame_errors++;
+                                                       error = false;
                                                }
+
                                                reset_ule(priv);
                                                priv->need_pusi = 1;
                                                continue;
@@ -535,6 +542,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                                from_where += 2;
                        }
 
+                       priv->ule_sndu_remain = priv->ule_sndu_len + 2;
                        /*
                         * State of current TS:
                         *   ts_remain (remaining bytes in the current TS cell)
@@ -544,6 +552,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                         */
                        switch (ts_remain) {
                                case 1:
+                                       priv->ule_sndu_remain--;
                                        priv->ule_sndu_type = from_where[0] << 8;
                                        priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */
                                        ts_remain -= 1; from_where += 1;
@@ -557,6 +566,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                                default: /* complete ULE header is present in current TS. */
                                        /* Extract ULE type field. */
                                        if (priv->ule_sndu_type_1) {
+                                               priv->ule_sndu_type_1 = 0;
                                                priv->ule_sndu_type |= from_where[0];
                                                from_where += 1; /* points to payload start. */
                                                ts_remain -= 1;
index e5f91f16ffa4ea51ae3f74cf06477eed56186a24..553b48ac1919068cddaa461e7302e3d004b54c4f 100644 (file)
@@ -76,6 +76,7 @@ config DVB_USB_DIB0700
        select DVB_S5H1411 if !DVB_FE_CUSTOMISE
        select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
        select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
+       select DVB_TUNER_DIB0090 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
@@ -134,6 +135,7 @@ config DVB_USB_M920X
        select DVB_TDA1004X if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
        help
          Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
          Currently, only devices with a product id of
@@ -264,7 +266,7 @@ config DVB_USB_DW2102
        select DVB_STB6000 if !DVB_FE_CUSTOMISE
        select DVB_CX24116 if !DVB_FE_CUSTOMISE
        select DVB_SI21XX if !DVB_FE_CUSTOMISE
-       select DVB_TDA10021 if !DVB_FE_CUSTOMISE
+       select DVB_TDA10023 if !DVB_FE_CUSTOMISE
        select DVB_MT312 if !DVB_FE_CUSTOMISE
        select DVB_ZL10039 if !DVB_FE_CUSTOMISE
        select DVB_DS3000 if !DVB_FE_CUSTOMISE
index 0eb49088916225c735f902ef3567b4c0b5d30b3b..11e9e85dac86b1f527ef43995e226ff1d14854fb 100644 (file)
@@ -1026,8 +1026,10 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
        cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
 
        if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
-                                &cxusb_dualdig4_rev2_config) < 0)
+                                    &cxusb_dualdig4_rev2_config) < 0) {
+               printk(KERN_WARNING "Unable to enumerate dib7000p\n");
                return -ENODEV;
+       }
 
        adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
                              &cxusb_dualdig4_rev2_config);
index 085c4e457e0e22c611f6e087d9fc4b6d98f7d8ad..b4afe6f8ed1900f22bc26bd00c1f53aef2f73b34 100644 (file)
 #define USB_PID_AVERMEDIA_A850                         0x850a
 #define USB_PID_AVERMEDIA_A805                         0xa805
 #define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
+#define USB_PID_TECHNOTREND_CONNECT_CT3650             0x300d
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY       0x005a
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2     0x0081
 #define USB_PID_TERRATEC_CINERGY_HT_USB_XE             0x0058
index 20ca9d9ee99b23aedb60d3ecf3e892c5d9ae71a5..a6de489a6a39e0c3ba63c897963317081ceeb416 100644 (file)
@@ -29,6 +29,8 @@
 
 #include "tda826x.h"
 #include "tda10086.h"
+#include "tda1002x.h"
+#include "tda827x.h"
 #include "lnbp21.h"
 
 /* debug */
@@ -150,7 +152,17 @@ static struct tda10086_config tda10086_config = {
        .xtal_freq = TDA10086_XTAL_16M,
 };
 
-static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
+static struct tda10023_config tda10023_config = {
+       .demod_address = 0x0c,
+       .invert = 0,
+       .xtal = 16000000,
+       .pll_m = 11,
+       .pll_p = 3,
+       .pll_n = 1,
+       .deltaf = 0xa511,
+};
+
+static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
 {
        if (usb_set_interface(adap->dev->udev,0,3) < 0)
                err("set interface to alts=3 failed");
@@ -163,7 +175,27 @@ static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
        return 0;
 }
 
-static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
+static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
+{
+       if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
+               err("set interface to alts=3 failed");
+       if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) {
+               deb_info("TDA10023 attach failed\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
+{
+       if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) {
+               printk(KERN_ERR "%s: No tda827x found!\n", __func__);
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
 {
        if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
                deb_info("TDA8263 attach failed\n");
@@ -180,6 +212,7 @@ static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
 /* DVB USB Driver stuff */
 static struct dvb_usb_device_properties ttusb2_properties;
 static struct dvb_usb_device_properties ttusb2_properties_s2400;
+static struct dvb_usb_device_properties ttusb2_properties_ct3650;
 
 static int ttusb2_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
@@ -187,6 +220,8 @@ static int ttusb2_probe(struct usb_interface *intf,
        if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
                                     THIS_MODULE, NULL, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &ttusb2_properties_ct3650,
                                     THIS_MODULE, NULL, adapter_nr))
                return 0;
        return -ENODEV;
@@ -197,6 +232,8 @@ static struct usb_device_id ttusb2_table [] = {
        { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
        { USB_DEVICE(USB_VID_TECHNOTREND,
                USB_PID_TECHNOTREND_CONNECT_S2400) },
+       { USB_DEVICE(USB_VID_TECHNOTREND,
+               USB_PID_TECHNOTREND_CONNECT_CT3650) },
        {}              /* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, ttusb2_table);
@@ -214,8 +251,8 @@ static struct dvb_usb_device_properties ttusb2_properties = {
                {
                        .streaming_ctrl   = NULL, // ttusb2_streaming_ctrl,
 
-                       .frontend_attach  = ttusb2_frontend_attach,
-                       .tuner_attach     = ttusb2_tuner_attach,
+                       .frontend_attach  = ttusb2_frontend_tda10086_attach,
+                       .tuner_attach     = ttusb2_tuner_tda826x_attach,
 
                        /* parameter for the MPEG2-data transfer */
                        .stream = {
@@ -266,8 +303,8 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
                {
                        .streaming_ctrl   = NULL,
 
-                       .frontend_attach  = ttusb2_frontend_attach,
-                       .tuner_attach     = ttusb2_tuner_attach,
+                       .frontend_attach  = ttusb2_frontend_tda10086_attach,
+                       .tuner_attach     = ttusb2_tuner_tda826x_attach,
 
                        /* parameter for the MPEG2-data transfer */
                        .stream = {
@@ -301,6 +338,52 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
        }
 };
 
+static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+       .usb_ctrl = CYPRESS_FX2,
+
+       .size_of_priv = sizeof(struct ttusb2_state),
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .streaming_ctrl   = NULL,
+
+                       .frontend_attach  = ttusb2_frontend_tda10023_attach,
+                       .tuner_attach = ttusb2_tuner_tda827x_attach,
+
+                       /* parameter for the MPEG2-data transfer */
+                       .stream = {
+                               .type = USB_ISOC,
+                               .count = 5,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .isoc = {
+                                               .framesperurb = 4,
+                                               .framesize = 940,
+                                               .interval = 1,
+                                       }
+                               }
+                       }
+               },
+       },
+
+       .power_ctrl       = ttusb2_power_ctrl,
+       .identify_state   = ttusb2_identify_state,
+
+       .i2c_algo         = &ttusb2_i2c_algo,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+
+       .num_device_descs = 1,
+       .devices = {
+               {   "Technotrend TT-connect CT-3650",
+                       .warm_ids = { &ttusb2_table[3], NULL },
+               },
+       }
+};
+
 static struct usb_driver ttusb2_driver = {
        .name           = "dvb_usb_ttusb2",
        .probe          = ttusb2_probe,
index 26333b4f4d3e9b039460513189383fcf45199745..b34ca7afb0e6bf7697fe188b5fd098a266ad5272 100644 (file)
@@ -58,7 +58,7 @@ static void rawiso_activity_cb(struct hpsb_iso *iso)
        num = hpsb_iso_n_ready(iso);
 
        if (!fdtv) {
-               dev_err(fdtv->device, "received at unknown iso channel\n");
+               pr_err("received at unknown iso channel\n");
                goto out;
        }
 
index 68dba3a4b4dab43fe61584cc7dec323db2765679..29cdbfe36852b865933ddd3b2f80f0dc0e5d57e6 100644 (file)
@@ -567,30 +567,6 @@ static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 
 /* ----------------------------------------------------------------------- */
 
-static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
-       switch (fmt->type) {
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
-       switch (fmt->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               /* Not yet implemented */
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int au8522_g_register(struct v4l2_subdev *sd,
                             struct v4l2_dbg_register *reg)
@@ -772,8 +748,6 @@ static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
 
 static const struct v4l2_subdev_video_ops au8522_video_ops = {
        .s_routing = au8522_s_video_routing,
-       .g_fmt = au8522_g_fmt,
-       .s_fmt = au8522_s_fmt,
        .s_stream = au8522_s_stream,
 };
 
index 78001e8bcdb74004c7930df01bcb1efa708ef922..fc61d9230db8bd1d0eb9541e8698da647f0a5367 100644 (file)
@@ -969,15 +969,12 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
        dprintk("%s\n", __func__);
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct ds3000_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct ds3000_state), GFP_KERNEL);
        if (state == NULL) {
                printk(KERN_ERR "Unable to kmalloc\n");
                goto error2;
        }
 
-       /* setup the state */
-       memset(state, 0, sizeof(struct ds3000_state));
-
        state->config = config;
        state->i2c = i2c;
        state->prevUCBS2 = 0;
index 42591ce1aaaddbd62c104a9ab47d807a3239e882..f36cab12bdc71964a463a79e4553738f00126dca 100644 (file)
@@ -303,7 +303,10 @@ static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
 
 static int stv6110x_sleep(struct dvb_frontend *fe)
 {
-       return stv6110x_set_mode(fe, TUNER_SLEEP);
+       if (fe->tuner_priv)
+               return stv6110x_set_mode(fe, TUNER_SLEEP);
+
+       return 0;
 }
 
 static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
index 692c3e226e83ff25efb04313a1aaafe0285de21a..4692a41ad95b8b598ab2b16c9a92a776db522898 100644 (file)
@@ -217,6 +217,19 @@ static struct ngene_info ngene_info_cineS2v5 = {
        .fw_version     = 15,
 };
 
+static struct ngene_info ngene_info_duoFlexS2 = {
+       .type           = NGENE_SIDEWINDER,
+       .name           = "Digital Devices DuoFlex S2 miniPCIe",
+       .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
+       .demod_attach   = {demod_attach_stv0900, demod_attach_stv0900},
+       .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110},
+       .fe_config      = {&fe_cineS2, &fe_cineS2},
+       .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1},
+       .lnb            = {0x0a, 0x08},
+       .tsf            = {3, 3},
+       .fw_version     = 15,
+};
+
 static struct ngene_info ngene_info_m780 = {
        .type           = NGENE_APP,
        .name           = "Aver M780 ATSC/QAM-B",
@@ -256,6 +269,8 @@ static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
        NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
        NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2),
        NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5),
+       NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlexS2),
+       NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlexS2),
        NGENE_ID(0x1461, 0x062e, ngene_info_m780),
        {0}
 };
index c8b4dfa0ab5f07f5df9ad6906730b618c2344426..4caeb163a66668da958cdae28058c2e0bb67a3af 100644 (file)
@@ -53,8 +53,6 @@ MODULE_PARM_DESC(debug, "Print debugging information.");
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-#define COMMAND_TIMEOUT_WORKAROUND
-
 #define dprintk        if (debug) printk
 
 #define ngwriteb(dat, adr)         writeb((dat), (char *)(dev->iomem + (adr)))
@@ -147,24 +145,24 @@ static void demux_tasklet(unsigned long data)
                } else {
                        if (chan->HWState == HWSTATE_RUN) {
                                u32 Flags = 0;
+                               IBufferExchange *exch1 = chan->pBufferExchange;
+                               IBufferExchange *exch2 = chan->pBufferExchange2;
                                if (Cur->ngeneBuffer.SR.Flags & 0x01)
                                        Flags |= BEF_EVEN_FIELD;
                                if (Cur->ngeneBuffer.SR.Flags & 0x20)
                                        Flags |= BEF_OVERFLOW;
-                               if (chan->pBufferExchange)
-                                       chan->pBufferExchange(chan,
-                                                             Cur->Buffer1,
-                                                             chan->
-                                                             Capture1Length,
-                                                             Cur->ngeneBuffer.
-                                                             SR.Clock, Flags);
-                               if (chan->pBufferExchange2)
-                                       chan->pBufferExchange2(chan,
-                                                              Cur->Buffer2,
-                                                              chan->
-                                                              Capture2Length,
-                                                              Cur->ngeneBuffer.
-                                                              SR.Clock, Flags);
+                               spin_unlock_irq(&chan->state_lock);
+                               if (exch1)
+                                       exch1(chan, Cur->Buffer1,
+                                               chan->Capture1Length,
+                                               Cur->ngeneBuffer.SR.Clock,
+                                               Flags);
+                               if (exch2)
+                                       exch2(chan, Cur->Buffer2,
+                                               chan->Capture2Length,
+                                               Cur->ngeneBuffer.SR.Clock,
+                                               Flags);
+                               spin_lock_irq(&chan->state_lock);
                        } else if (chan->HWState != HWSTATE_STOP)
                                chan->HWState = HWSTATE_RUN;
                }
@@ -572,11 +570,7 @@ static int ngene_command_stream_control(struct ngene *dev, u8 stream,
        u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700);
        u16 BsSDO = 0x9B00;
 
-       /* down(&dev->stream_mutex); */
-       while (down_trylock(&dev->stream_mutex)) {
-               printk(KERN_INFO DEVICE_NAME ": SC locked\n");
-               msleep(1);
-       }
+       down(&dev->stream_mutex);
        memset(&com, 0, sizeof(com));
        com.cmd.hdr.Opcode = CMD_CONTROL;
        com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2;
@@ -1252,14 +1246,17 @@ static int ngene_load_firm(struct ngene *dev)
                version = 15;
                size = 23466;
                fw_name = "ngene_15.fw";
+               dev->cmd_timeout_workaround = true;
                break;
        case 16:
                size = 23498;
                fw_name = "ngene_16.fw";
+               dev->cmd_timeout_workaround = true;
                break;
        case 17:
                size = 24446;
                fw_name = "ngene_17.fw";
+               dev->cmd_timeout_workaround = true;
                break;
        }
 
@@ -1299,11 +1296,16 @@ static void ngene_stop(struct ngene *dev)
        ngwritel(0, NGENE_EVENT);
        ngwritel(0, NGENE_EVENT_HI);
        free_irq(dev->pci_dev->irq, dev);
+#ifdef CONFIG_PCI_MSI
+       if (dev->msi_enabled)
+               pci_disable_msi(dev->pci_dev);
+#endif
 }
 
 static int ngene_start(struct ngene *dev)
 {
        int stat;
+       unsigned long flags;
        int i;
 
        pci_set_master(dev->pci_dev);
@@ -1333,6 +1335,28 @@ static int ngene_start(struct ngene *dev)
        if (stat < 0)
                goto fail;
 
+#ifdef CONFIG_PCI_MSI
+       /* enable MSI if kernel and card support it */
+       if (pci_msi_enabled() && dev->card_info->msi_supported) {
+               ngwritel(0, NGENE_INT_ENABLE);
+               free_irq(dev->pci_dev->irq, dev);
+               stat = pci_enable_msi(dev->pci_dev);
+               if (stat) {
+                       printk(KERN_INFO DEVICE_NAME
+                               ": MSI not available\n");
+                       flags = IRQF_SHARED;
+               } else {
+                       flags = 0;
+                       dev->msi_enabled = true;
+               }
+               stat = request_irq(dev->pci_dev->irq, irq_handler,
+                                       flags, "nGene", dev);
+               if (stat < 0)
+                       goto fail2;
+               ngwritel(1, NGENE_INT_ENABLE);
+       }
+#endif
+
        stat = ngene_i2c_init(dev, 0);
        if (stat < 0)
                goto fail;
@@ -1358,10 +1382,18 @@ static int ngene_start(struct ngene *dev)
                        bconf = BUFFER_CONFIG_3333;
                stat = ngene_command_config_buf(dev, bconf);
        }
-       return stat;
+       if (!stat)
+               return stat;
+
+       /* otherwise error: fall through */
 fail:
        ngwritel(0, NGENE_INT_ENABLE);
        free_irq(dev->pci_dev->irq, dev);
+#ifdef CONFIG_PCI_MSI
+fail2:
+       if (dev->msi_enabled)
+               pci_disable_msi(dev->pci_dev);
+#endif
        return stat;
 }
 
@@ -1379,10 +1411,8 @@ static void release_channel(struct ngene_channel *chan)
        struct ngene_info *ni = dev->card_info;
        int io = ni->io_type[chan->number];
 
-#ifdef COMMAND_TIMEOUT_WORKAROUND
-       if (chan->running)
+       if (chan->dev->cmd_timeout_workaround && chan->running)
                set_transfer(chan, 0);
-#endif
 
        tasklet_kill(&chan->demux_tasklet);
 
index 96013eb353cda0db1e46724d3e0542e91888a61a..48f980b21d663ad94b89b17689d62737104b6ac4 100644 (file)
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
 #include <linux/timer.h>
-#include <linux/version.h>
 #include <linux/byteorder/generic.h>
 #include <linux/firmware.h>
 #include <linux/vmalloc.h>
 
 #include "ngene.h"
 
-#define COMMAND_TIMEOUT_WORKAROUND
-
 
 /****************************************************************************/
 /* COMMAND API interface ****************************************************/
@@ -69,9 +66,7 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
        struct ngene_channel *chan = priv;
 
 
-#ifdef COMMAND_TIMEOUT_WORKAROUND
        if (chan->users > 0)
-#endif
                dvb_dmx_swfilter(&chan->demux, buf, len);
        return NULL;
 }
@@ -106,11 +101,8 @@ int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed)
        struct ngene_channel *chan = dvbdmx->priv;
 
        if (chan->users == 0) {
-#ifdef COMMAND_TIMEOUT_WORKAROUND
-               if (!chan->running)
-#endif
+               if (!chan->dev->cmd_timeout_workaround || !chan->running)
                        set_transfer(chan, 1);
-               /* msleep(10); */
        }
 
        return ++chan->users;
@@ -124,9 +116,8 @@ int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
        if (--chan->users)
                return chan->users;
 
-#ifndef COMMAND_TIMEOUT_WORKAROUND
-       set_transfer(chan, 0);
-#endif
+       if (!chan->dev->cmd_timeout_workaround)
+               set_transfer(chan, 0);
 
        return 0;
 }
index 2ef54ca6baddc2399c7043b516ba3502afcb1424..477fe0aade866bea99040fc8ca8b134883fc2919 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/pci_ids.h>
 #include <linux/smp_lock.h>
 #include <linux/timer.h>
-#include <linux/version.h>
 #include <linux/byteorder/generic.h>
 #include <linux/firmware.h>
 #include <linux/vmalloc.h>
index 676fcbb79026847cfb8694c5d22d25d711195ddd..8fb4200f83f847e73d0f17b6e70e0a33dd107df1 100644 (file)
@@ -725,6 +725,8 @@ struct ngene {
        u32                   device_version;
        u32                   fw_interface_version;
        u32                   icounts;
+       bool                  msi_enabled;
+       bool                  cmd_timeout_workaround;
 
        u8                   *CmdDoneByte;
        int                   BootFirmware;
@@ -797,6 +799,7 @@ struct ngene_info {
 #define NGENE_VBOX_V2   7
 
        int   fw_version;
+       bool  msi_supported;
        char *name;
 
        int   io_type[MAX_STREAM];
index d8d4214fd65f2c7af9d3af1a263a30f9dc24e3a9..32a7ec65ec42f1c40fbb4e4576b56cded5045902 100644 (file)
@@ -68,13 +68,14 @@ config DVB_BUDGET
        select DVB_VES1820 if !DVB_FE_CUSTOMISE
        select DVB_L64781 if !DVB_FE_CUSTOMISE
        select DVB_TDA8083 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10021 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10023 if !DVB_FE_CUSTOMISE
        select DVB_S5H1420 if !DVB_FE_CUSTOMISE
        select DVB_TDA10086 if !DVB_FE_CUSTOMISE
        select DVB_TDA826X if !DVB_FE_CUSTOMISE
        select DVB_LNBP21 if !DVB_FE_CUSTOMISE
        select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+       select DVB_ISL6423 if !DVB_FE_CUSTOMISE
+       select DVB_STV090x if !DVB_FE_CUSTOMISE
+       select DVB_STV6110x if !DVB_FE_CUSTOMISE
        help
          Support for simple SAA7146 based DVB cards (so called Budget-
          or Nova-PCI cards) without onboard MPEG2 decoder, and without
index 46171439633136fc23b6b8e869abba15b1a9a8e9..13ac9e3ab1210dab3cbe4d9ae469af49a98c434b 100644 (file)
@@ -215,6 +215,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
                break;
        case 0x1010:
        case 0x1017:
+       case 0x1019:
        case 0x101a:
                /* for the Technotrend 1500 bundled remote */
                ir_codes = RC_MAP_TT_1500;
index a5844d08d8b7917c19702d9f7879a1bc0244aba4..67a4ec8768a6145ecfd6fb1d44095bfb51f29fdc 100644 (file)
@@ -482,7 +482,6 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client)
        cancel_work_sync(&radio->radio_work);
        video_unregister_device(radio->videodev);
        kfree(radio);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index ad9e6f9c22e9a04473565a245c254ec7f21a3089..bdbc9d305419d8778d7bfceded703e1fb55d4c9b 100644 (file)
@@ -646,7 +646,7 @@ config VIDEO_PMS
 
 config VIDEO_BWQCAM
        tristate "Quickcam BW Video For Linux"
-       depends on PARPORT && VIDEO_V4L1
+       depends on PARPORT && VIDEO_V4L2
        help
          Say Y have if you the black and white version of the QuickCam
          camera. See the next option for the color version.
@@ -656,7 +656,7 @@ config VIDEO_BWQCAM
 
 config VIDEO_CQCAM
        tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && PARPORT && VIDEO_V4L1
+       depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2
        help
          This is the video4linux driver for the colour version of the
          Connectix QuickCam.  If you have one of these cameras, say Y here,
index 35390d4717b97a4f5824a69a4c2545b236485323..1573392f74bd36a2fb3d010d49238222c1f2344b 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <linux/videodev2.h>
 
 #include <media/ak881x.h>
@@ -141,7 +142,7 @@ static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd,
        return ak881x_try_g_mbus_fmt(sd, mf);
 }
 
-static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, int index,
+static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
                                enum v4l2_mbus_pixelcode *code)
 {
        if (index)
index 3c9e754d73a053199376098170ee5e80b9a86f37..935e0c9a96744aa1e4f0cd3d443c8ee4c8b407d2 100644 (file)
@@ -66,19 +66,58 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/parport.h>
 #include <linux/sched.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
+#include <linux/version.h>
+#include <linux/videodev2.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
-
-#include "bw-qcam.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+
+/* One from column A... */
+#define QC_NOTSET 0
+#define QC_UNIDIR 1
+#define QC_BIDIR  2
+#define QC_SERIAL 3
+
+/* ... and one from column B */
+#define QC_ANY          0x00
+#define QC_FORCE_UNIDIR 0x10
+#define QC_FORCE_BIDIR  0x20
+#define QC_FORCE_SERIAL 0x30
+/* in the port_mode member */
+
+#define QC_MODE_MASK    0x07
+#define QC_FORCE_MASK   0x70
+
+#define MAX_HEIGHT 243
+#define MAX_WIDTH 336
+
+/* Bit fields for status flags */
+#define QC_PARAM_CHANGE        0x01 /* Camera status change has occurred */
+
+struct qcam {
+       struct v4l2_device v4l2_dev;
+       struct video_device vdev;
+       struct pardevice *pdev;
+       struct parport *pport;
+       struct mutex lock;
+       int width, height;
+       int bpp;
+       int mode;
+       int contrast, brightness, whitebal;
+       int port_mode;
+       int transfer_scale;
+       int top, left;
+       int status;
+       unsigned int saved_bits;
+       unsigned long in_use;
+};
 
 static unsigned int maxpoll = 250;   /* Maximum busy-loop count for qcam I/O */
 static unsigned int yieldlines = 4;  /* Yield after this many during capture */
@@ -93,22 +132,26 @@ module_param(video_nr, int, 0);
  * immediately attempt to initialize qcam */
 module_param(force_init, int, 0);
 
-static inline int read_lpstatus(struct qcam_device *q)
+#define MAX_CAMS 4
+static struct qcam *qcams[MAX_CAMS];
+static unsigned int num_cams;
+
+static inline int read_lpstatus(struct qcam *q)
 {
        return parport_read_status(q->pport);
 }
 
-static inline int read_lpdata(struct qcam_device *q)
+static inline int read_lpdata(struct qcam *q)
 {
        return parport_read_data(q->pport);
 }
 
-static inline void write_lpdata(struct qcam_device *q, int d)
+static inline void write_lpdata(struct qcam *q, int d)
 {
        parport_write_data(q->pport, d);
 }
 
-static inline void write_lpcontrol(struct qcam_device *q, int d)
+static void write_lpcontrol(struct qcam *q, int d)
 {
        if (d & 0x20) {
                /* Set bidirectional mode to reverse (data in) */
@@ -124,126 +167,11 @@ static inline void write_lpcontrol(struct qcam_device *q, int d)
        parport_write_control(q->pport, d);
 }
 
-static int qc_waithand(struct qcam_device *q, int val);
-static int qc_command(struct qcam_device *q, int command);
-static int qc_readparam(struct qcam_device *q);
-static int qc_setscanmode(struct qcam_device *q);
-static int qc_readbytes(struct qcam_device *q, char buffer[]);
-
-static struct video_device qcam_template;
-
-static int qc_calibrate(struct qcam_device *q)
-{
-       /*
-        *      Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
-        *      The white balance is an individiual value for each
-        *      quickcam.
-        */
-
-       int value;
-       int count = 0;
-
-       qc_command(q, 27);      /* AutoAdjustOffset */
-       qc_command(q, 0);       /* Dummy Parameter, ignored by the camera */
-
-       /* GetOffset (33) will read 255 until autocalibration */
-       /* is finished. After that, a value of 1-254 will be */
-       /* returned. */
-
-       do {
-               qc_command(q, 33);
-               value = qc_readparam(q);
-               mdelay(1);
-               schedule();
-               count++;
-       } while (value == 0xff && count < 2048);
-
-       q->whitebal = value;
-       return value;
-}
-
-/* Initialize the QuickCam driver control structure.  This is where
- * defaults are set for people who don't have a config file.*/
-
-static struct qcam_device *qcam_init(struct parport *port)
-{
-       struct qcam_device *q;
-
-       q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
-       if (q == NULL)
-               return NULL;
-
-       q->pport = port;
-       q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
-                       NULL, 0, NULL);
-       if (q->pdev == NULL) {
-               printk(KERN_ERR "bw-qcam: couldn't register for %s.\n",
-                               port->name);
-               kfree(q);
-               return NULL;
-       }
-
-       memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
-
-       mutex_init(&q->lock);
-
-       q->port_mode = (QC_ANY | QC_NOTSET);
-       q->width = 320;
-       q->height = 240;
-       q->bpp = 4;
-       q->transfer_scale = 2;
-       q->contrast = 192;
-       q->brightness = 180;
-       q->whitebal = 105;
-       q->top = 1;
-       q->left = 14;
-       q->mode = -1;
-       q->status = QC_PARAM_CHANGE;
-       return q;
-}
-
-
-/* qc_command is probably a bit of a misnomer -- it's used to send
- * bytes *to* the camera.  Generally, these bytes are either commands
- * or arguments to commands, so the name fits, but it still bugs me a
- * bit.  See the documentation for a list of commands. */
-
-static int qc_command(struct qcam_device *q, int command)
-{
-       int n1, n2;
-       int cmd;
-
-       write_lpdata(q, command);
-       write_lpcontrol(q, 6);
-
-       n1 = qc_waithand(q, 1);
-
-       write_lpcontrol(q, 0xe);
-       n2 = qc_waithand(q, 0);
-
-       cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
-       return cmd;
-}
-
-static int qc_readparam(struct qcam_device *q)
-{
-       int n1, n2;
-       int cmd;
-
-       write_lpcontrol(q, 6);
-       n1 = qc_waithand(q, 1);
-
-       write_lpcontrol(q, 0xe);
-       n2 = qc_waithand(q, 0);
-
-       cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
-       return cmd;
-}
 
 /* qc_waithand busy-waits for a handshake signal from the QuickCam.
  * Almost all communication with the camera requires handshaking. */
 
-static int qc_waithand(struct qcam_device *q, int val)
+static int qc_waithand(struct qcam *q, int val)
 {
        int status;
        int runs = 0;
@@ -286,7 +214,7 @@ static int qc_waithand(struct qcam_device *q, int val)
  * (bit 3 of status register).  It also returns the last value read,
  * since this data is useful. */
 
-static unsigned int qc_waithand2(struct qcam_device *q, int val)
+static unsigned int qc_waithand2(struct qcam *q, int val)
 {
        unsigned int status;
        int runs = 0;
@@ -309,6 +237,43 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val)
        return status;
 }
 
+/* qc_command is probably a bit of a misnomer -- it's used to send
+ * bytes *to* the camera.  Generally, these bytes are either commands
+ * or arguments to commands, so the name fits, but it still bugs me a
+ * bit.  See the documentation for a list of commands. */
+
+static int qc_command(struct qcam *q, int command)
+{
+       int n1, n2;
+       int cmd;
+
+       write_lpdata(q, command);
+       write_lpcontrol(q, 6);
+
+       n1 = qc_waithand(q, 1);
+
+       write_lpcontrol(q, 0xe);
+       n2 = qc_waithand(q, 0);
+
+       cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
+       return cmd;
+}
+
+static int qc_readparam(struct qcam *q)
+{
+       int n1, n2;
+       int cmd;
+
+       write_lpcontrol(q, 6);
+       n1 = qc_waithand(q, 1);
+
+       write_lpcontrol(q, 0xe);
+       n2 = qc_waithand(q, 0);
+
+       cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
+       return cmd;
+}
+
 
 /* Try to detect a QuickCam.  It appears to flash the upper 4 bits of
    the status register at 5-10 Hz.  This is only used in the autoprobe
@@ -317,7 +282,7 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val)
    almost completely safe, while their method screws up my printer if
    I plug it in before the camera. */
 
-static int qc_detect(struct qcam_device *q)
+static int qc_detect(struct qcam *q)
 {
        int reg, lastreg;
        int count = 0;
@@ -358,41 +323,6 @@ static int qc_detect(struct qcam_device *q)
        }
 }
 
-
-/* Reset the QuickCam.  This uses the same sequence the Windows
- * QuickPic program uses.  Someone with a bi-directional port should
- * check that bi-directional mode is detected right, and then
- * implement bi-directional mode in qc_readbyte(). */
-
-static void qc_reset(struct qcam_device *q)
-{
-       switch (q->port_mode & QC_FORCE_MASK) {
-       case QC_FORCE_UNIDIR:
-               q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
-               break;
-
-       case QC_FORCE_BIDIR:
-               q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
-               break;
-
-       case QC_ANY:
-               write_lpcontrol(q, 0x20);
-               write_lpdata(q, 0x75);
-
-               if (read_lpdata(q) != 0x75)
-                       q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
-               else
-                       q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
-               break;
-       }
-
-       write_lpcontrol(q, 0xb);
-       udelay(250);
-       write_lpcontrol(q, 0xe);
-       qc_setscanmode(q);              /* in case port_mode changed */
-}
-
-
 /* Decide which scan mode to use.  There's no real requirement that
  * the scanmode match the resolution in q->height and q-> width -- the
  * camera takes the picture at the resolution specified in the
@@ -402,7 +332,7 @@ static void qc_reset(struct qcam_device *q)
  * returned.  If the scan is smaller, then the rest of the image
  * returned contains garbage. */
 
-static int qc_setscanmode(struct qcam_device *q)
+static int qc_setscanmode(struct qcam *q)
 {
        int old_mode = q->mode;
 
@@ -442,10 +372,45 @@ static int qc_setscanmode(struct qcam_device *q)
 }
 
 
+/* Reset the QuickCam.  This uses the same sequence the Windows
+ * QuickPic program uses.  Someone with a bi-directional port should
+ * check that bi-directional mode is detected right, and then
+ * implement bi-directional mode in qc_readbyte(). */
+
+static void qc_reset(struct qcam *q)
+{
+       switch (q->port_mode & QC_FORCE_MASK) {
+       case QC_FORCE_UNIDIR:
+               q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
+               break;
+
+       case QC_FORCE_BIDIR:
+               q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
+               break;
+
+       case QC_ANY:
+               write_lpcontrol(q, 0x20);
+               write_lpdata(q, 0x75);
+
+               if (read_lpdata(q) != 0x75)
+                       q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
+               else
+                       q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
+               break;
+       }
+
+       write_lpcontrol(q, 0xb);
+       udelay(250);
+       write_lpcontrol(q, 0xe);
+       qc_setscanmode(q);              /* in case port_mode changed */
+}
+
+
+
 /* Reset the QuickCam and program for brightness, contrast,
  * white-balance, and resolution. */
 
-static void qc_set(struct qcam_device *q)
+static void qc_set(struct qcam *q)
 {
        int val;
        int val2;
@@ -499,7 +464,7 @@ static void qc_set(struct qcam_device *q)
    the supplied buffer.  It returns the number of bytes read,
    or -1 on error. */
 
-static inline int qc_readbytes(struct qcam_device *q, char buffer[])
+static inline int qc_readbytes(struct qcam *q, char buffer[])
 {
        int ret = 1;
        unsigned int hi, lo;
@@ -590,7 +555,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
  * n=2^(bit depth)-1.  Ask me for more details if you don't understand
  * this. */
 
-static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len)
+static long qc_capture(struct qcam *q, char __user *buf, unsigned long len)
 {
        int i, j, k, yield;
        int bytes;
@@ -674,171 +639,206 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
  *     Video4linux interfacing
  */
 
-static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static int qcam_querycap(struct file *file, void  *priv,
+                                       struct v4l2_capability *vcap)
 {
-       struct video_device *dev = video_devdata(file);
-       struct qcam_device *qcam = (struct qcam_device *)dev;
-
-       switch (cmd) {
-       case VIDIOCGCAP:
-               {
-                       struct video_capability *b = arg;
-                       strcpy(b->name, "Quickcam");
-                       b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES|VID_TYPE_MONOCHROME;
-                       b->channels = 1;
-                       b->audios = 0;
-                       b->maxwidth = 320;
-                       b->maxheight = 240;
-                       b->minwidth = 80;
-                       b->minheight = 60;
-                       return 0;
-               }
-       case VIDIOCGCHAN:
-               {
-                       struct video_channel *v = arg;
-                       if (v->channel != 0)
-                               return -EINVAL;
-                       v->flags = 0;
-                       v->tuners = 0;
-                       /* Good question.. its composite or SVHS so.. */
-                       v->type = VIDEO_TYPE_CAMERA;
-                       strcpy(v->name, "Camera");
-                       return 0;
-               }
-       case VIDIOCSCHAN:
-               {
-                       struct video_channel *v = arg;
-                       if (v->channel != 0)
-                               return -EINVAL;
-                       return 0;
-               }
-       case VIDIOCGTUNER:
-               {
-                       struct video_tuner *v = arg;
-                       if (v->tuner)
-                               return -EINVAL;
-                       strcpy(v->name, "Format");
-                       v->rangelow = 0;
-                       v->rangehigh = 0;
-                       v->flags = 0;
-                       v->mode = VIDEO_MODE_AUTO;
-                       return 0;
-               }
-       case VIDIOCSTUNER:
-               {
-                       struct video_tuner *v = arg;
-                       if (v->tuner)
-                               return -EINVAL;
-                       if (v->mode != VIDEO_MODE_AUTO)
-                               return -EINVAL;
-                       return 0;
-               }
-       case VIDIOCGPICT:
-               {
-                       struct video_picture *p = arg;
-                       p->colour = 0x8000;
-                       p->hue = 0x8000;
-                       p->brightness = qcam->brightness << 8;
-                       p->contrast = qcam->contrast << 8;
-                       p->whiteness = qcam->whitebal << 8;
-                       p->depth = qcam->bpp;
-                       p->palette = VIDEO_PALETTE_GREY;
-                       return 0;
-               }
-       case VIDIOCSPICT:
-               {
-                       struct video_picture *p = arg;
-                       if (p->palette != VIDEO_PALETTE_GREY)
-                               return -EINVAL;
-                       if (p->depth != 4 && p->depth != 6)
-                               return -EINVAL;
-
-                       /*
-                        *      Now load the camera.
-                        */
-
-                       qcam->brightness = p->brightness >> 8;
-                       qcam->contrast = p->contrast >> 8;
-                       qcam->whitebal = p->whiteness >> 8;
-                       qcam->bpp = p->depth;
-
-                       mutex_lock(&qcam->lock);
-                       qc_setscanmode(qcam);
-                       mutex_unlock(&qcam->lock);
-                       qcam->status |= QC_PARAM_CHANGE;
+       struct qcam *qcam = video_drvdata(file);
 
-                       return 0;
-               }
-       case VIDIOCSWIN:
-               {
-                       struct video_window *vw = arg;
-                       if (vw->flags)
-                               return -EINVAL;
-                       if (vw->clipcount)
-                               return -EINVAL;
-                       if (vw->height < 60 || vw->height > 240)
-                               return -EINVAL;
-                       if (vw->width < 80 || vw->width > 320)
-                               return -EINVAL;
-
-                       qcam->width = 320;
-                       qcam->height = 240;
-                       qcam->transfer_scale = 4;
-
-                       if (vw->width >= 160 && vw->height >= 120)
-                               qcam->transfer_scale = 2;
-                       if (vw->width >= 320 && vw->height >= 240) {
-                               qcam->width = 320;
-                               qcam->height = 240;
-                               qcam->transfer_scale = 1;
-                       }
-                       mutex_lock(&qcam->lock);
-                       qc_setscanmode(qcam);
-                       mutex_unlock(&qcam->lock);
+       strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
+       strlcpy(vcap->card, "B&W Quickcam", sizeof(vcap->card));
+       strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
+       vcap->version = KERNEL_VERSION(0, 0, 2);
+       vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+       return 0;
+}
 
-                       /* We must update the camera before we grab. We could
-                          just have changed the grab size */
-                       qcam->status |= QC_PARAM_CHANGE;
+static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+       if (vin->index > 0)
+               return -EINVAL;
+       strlcpy(vin->name, "Camera", sizeof(vin->name));
+       vin->type = V4L2_INPUT_TYPE_CAMERA;
+       vin->audioset = 0;
+       vin->tuner = 0;
+       vin->std = 0;
+       vin->status = 0;
+       return 0;
+}
 
-                       /* Ok we figured out what to use from our wide choice */
-                       return 0;
-               }
-       case VIDIOCGWIN:
-               {
-                       struct video_window *vw = arg;
+static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+       *inp = 0;
+       return 0;
+}
 
-                       memset(vw, 0, sizeof(*vw));
-                       vw->width = qcam->width / qcam->transfer_scale;
-                       vw->height = qcam->height / qcam->transfer_scale;
-                       return 0;
-               }
-       case VIDIOCKEY:
-               return 0;
-       case VIDIOCCAPTURE:
-       case VIDIOCGFBUF:
-       case VIDIOCSFBUF:
-       case VIDIOCGFREQ:
-       case VIDIOCSFREQ:
-       case VIDIOCGAUDIO:
-       case VIDIOCSAUDIO:
-               return -EINVAL;
+static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+       return (inp > 0) ? -EINVAL : 0;
+}
+
+static int qcam_queryctrl(struct file *file, void *priv,
+                                       struct v4l2_queryctrl *qc)
+{
+       switch (qc->id) {
+       case V4L2_CID_BRIGHTNESS:
+               return v4l2_ctrl_query_fill(qc, 0, 255, 1, 180);
+       case V4L2_CID_CONTRAST:
+               return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192);
+       case V4L2_CID_GAMMA:
+               return v4l2_ctrl_query_fill(qc, 0, 255, 1, 105);
+       }
+       return -EINVAL;
+}
+
+static int qcam_g_ctrl(struct file *file, void *priv,
+                                       struct v4l2_control *ctrl)
+{
+       struct qcam *qcam = video_drvdata(file);
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ctrl->value = qcam->brightness;
+               break;
+       case V4L2_CID_CONTRAST:
+               ctrl->value = qcam->contrast;
+               break;
+       case V4L2_CID_GAMMA:
+               ctrl->value = qcam->whitebal;
+               break;
        default:
-               return -ENOIOCTLCMD;
+               ret = -EINVAL;
+               break;
        }
+       return ret;
+}
+
+static int qcam_s_ctrl(struct file *file, void *priv,
+                                       struct v4l2_control *ctrl)
+{
+       struct qcam *qcam = video_drvdata(file);
+       int ret = 0;
+
+       mutex_lock(&qcam->lock);
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               qcam->brightness = ctrl->value;
+               break;
+       case V4L2_CID_CONTRAST:
+               qcam->contrast = ctrl->value;
+               break;
+       case V4L2_CID_GAMMA:
+               qcam->whitebal = ctrl->value;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       if (ret == 0) {
+               qc_setscanmode(qcam);
+               qcam->status |= QC_PARAM_CHANGE;
+       }
+       mutex_unlock(&qcam->lock);
+       return ret;
+}
+
+static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct qcam *qcam = video_drvdata(file);
+       struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+       pix->width = qcam->width / qcam->transfer_scale;
+       pix->height = qcam->height / qcam->transfer_scale;
+       pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
+       pix->field = V4L2_FIELD_NONE;
+       pix->bytesperline = qcam->width;
+       pix->sizeimage = qcam->width * qcam->height;
+       /* Just a guess */
+       pix->colorspace = V4L2_COLORSPACE_SRGB;
+       return 0;
+}
+
+static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+       if (pix->height <= 60 || pix->width <= 80) {
+               pix->height = 60;
+               pix->width = 80;
+       } else if (pix->height <= 120 || pix->width <= 160) {
+               pix->height = 120;
+               pix->width = 160;
+       } else {
+               pix->height = 240;
+               pix->width = 320;
+       }
+       if (pix->pixelformat != V4L2_PIX_FMT_Y4 &&
+           pix->pixelformat != V4L2_PIX_FMT_Y6)
+               pix->pixelformat = V4L2_PIX_FMT_Y4;
+       pix->field = V4L2_FIELD_NONE;
+       pix->bytesperline = pix->width;
+       pix->sizeimage = pix->width * pix->height;
+       /* Just a guess */
+       pix->colorspace = V4L2_COLORSPACE_SRGB;
+       return 0;
+}
+
+static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct qcam *qcam = video_drvdata(file);
+       struct v4l2_pix_format *pix = &fmt->fmt.pix;
+       int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
+
+       if (ret)
+               return ret;
+       qcam->width = 320;
+       qcam->height = 240;
+       if (pix->height == 60)
+               qcam->transfer_scale = 4;
+       else if (pix->height == 120)
+               qcam->transfer_scale = 2;
+       else
+               qcam->transfer_scale = 1;
+       if (pix->pixelformat == V4L2_PIX_FMT_Y6)
+               qcam->bpp = 6;
+       else
+               qcam->bpp = 4;
+
+       mutex_lock(&qcam->lock);
+       qc_setscanmode(qcam);
+       /* We must update the camera before we grab. We could
+          just have changed the grab size */
+       qcam->status |= QC_PARAM_CHANGE;
+       mutex_unlock(&qcam->lock);
        return 0;
 }
 
-static long qcam_ioctl(struct file *file,
-               unsigned int cmd, unsigned long arg)
+static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
 {
-       return video_usercopy(file, cmd, arg, qcam_do_ioctl);
+       static struct v4l2_fmtdesc formats[] = {
+               { 0, 0, 0,
+                 "4-Bit Monochrome", V4L2_PIX_FMT_Y4,
+                 { 0, 0, 0, 0 }
+               },
+               { 0, 0, 0,
+                 "6-Bit Monochrome", V4L2_PIX_FMT_Y6,
+                 { 0, 0, 0, 0 }
+               },
+       };
+       enum v4l2_buf_type type = fmt->type;
+
+       if (fmt->index > 1)
+               return -EINVAL;
+
+       *fmt = formats[fmt->index];
+       fmt->type = type;
+       return 0;
 }
 
 static ssize_t qcam_read(struct file *file, char __user *buf,
                size_t count, loff_t *ppos)
 {
-       struct video_device *v = video_devdata(file);
-       struct qcam_device *qcam = (struct qcam_device *)v;
+       struct qcam *qcam = video_drvdata(file);
        int len;
        parport_claim_or_block(qcam->pdev);
 
@@ -858,43 +858,112 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
        return len;
 }
 
-static int qcam_exclusive_open(struct file *file)
+static const struct v4l2_file_operations qcam_fops = {
+       .owner          = THIS_MODULE,
+       .ioctl          = video_ioctl2,
+       .read           = qcam_read,
+};
+
+static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
+       .vidioc_querycap                    = qcam_querycap,
+       .vidioc_g_input                     = qcam_g_input,
+       .vidioc_s_input                     = qcam_s_input,
+       .vidioc_enum_input                  = qcam_enum_input,
+       .vidioc_queryctrl                   = qcam_queryctrl,
+       .vidioc_g_ctrl                      = qcam_g_ctrl,
+       .vidioc_s_ctrl                      = qcam_s_ctrl,
+       .vidioc_enum_fmt_vid_cap            = qcam_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap               = qcam_g_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap               = qcam_s_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap             = qcam_try_fmt_vid_cap,
+};
+
+/* Initialize the QuickCam driver control structure.  This is where
+ * defaults are set for people who don't have a config file.*/
+
+static struct qcam *qcam_init(struct parport *port)
 {
-       struct video_device *dev = video_devdata(file);
-       struct qcam_device *qcam = (struct qcam_device *)dev;
+       struct qcam *qcam;
+       struct v4l2_device *v4l2_dev;
+
+       qcam = kzalloc(sizeof(struct qcam), GFP_KERNEL);
+       if (qcam == NULL)
+               return NULL;
+
+       v4l2_dev = &qcam->v4l2_dev;
+       strlcpy(v4l2_dev->name, "bw-qcam", sizeof(v4l2_dev->name));
 
-       return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
+       if (v4l2_device_register(NULL, v4l2_dev) < 0) {
+               v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+               return NULL;
+       }
+
+       qcam->pport = port;
+       qcam->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
+                       NULL, 0, NULL);
+       if (qcam->pdev == NULL) {
+               v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
+               kfree(qcam);
+               return NULL;
+       }
+
+       strlcpy(qcam->vdev.name, "Connectix QuickCam", sizeof(qcam->vdev.name));
+       qcam->vdev.v4l2_dev = v4l2_dev;
+       qcam->vdev.fops = &qcam_fops;
+       qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
+       qcam->vdev.release = video_device_release_empty;
+       video_set_drvdata(&qcam->vdev, qcam);
+
+       mutex_init(&qcam->lock);
+
+       qcam->port_mode = (QC_ANY | QC_NOTSET);
+       qcam->width = 320;
+       qcam->height = 240;
+       qcam->bpp = 4;
+       qcam->transfer_scale = 2;
+       qcam->contrast = 192;
+       qcam->brightness = 180;
+       qcam->whitebal = 105;
+       qcam->top = 1;
+       qcam->left = 14;
+       qcam->mode = -1;
+       qcam->status = QC_PARAM_CHANGE;
+       return qcam;
 }
 
-static int qcam_exclusive_release(struct file *file)
+static int qc_calibrate(struct qcam *q)
 {
-       struct video_device *dev = video_devdata(file);
-       struct qcam_device *qcam = (struct qcam_device *)dev;
+       /*
+        *      Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
+        *      The white balance is an individual value for each
+        *      quickcam.
+        */
 
-       clear_bit(0, &qcam->in_use);
-       return 0;
-}
+       int value;
+       int count = 0;
 
-static const struct v4l2_file_operations qcam_fops = {
-       .owner          = THIS_MODULE,
-       .open           = qcam_exclusive_open,
-       .release        = qcam_exclusive_release,
-       .ioctl          = qcam_ioctl,
-       .read           = qcam_read,
-};
-static struct video_device qcam_template = {
-       .name           = "Connectix Quickcam",
-       .fops           = &qcam_fops,
-       .release        = video_device_release_empty,
-};
+       qc_command(q, 27);      /* AutoAdjustOffset */
+       qc_command(q, 0);       /* Dummy Parameter, ignored by the camera */
 
-#define MAX_CAMS 4
-static struct qcam_device *qcams[MAX_CAMS];
-static unsigned int num_cams;
+       /* GetOffset (33) will read 255 until autocalibration */
+       /* is finished. After that, a value of 1-254 will be */
+       /* returned. */
+
+       do {
+               qc_command(q, 33);
+               value = qc_readparam(q);
+               mdelay(1);
+               schedule();
+               count++;
+       } while (value == 0xff && count < 2048);
+
+       q->whitebal = value;
+       return value;
+}
 
 static int init_bwqcam(struct parport *port)
 {
-       struct qcam_device *qcam;
+       struct qcam *qcam;
 
        if (num_cams == MAX_CAMS) {
                printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS);
@@ -919,7 +988,7 @@ static int init_bwqcam(struct parport *port)
 
        parport_release(qcam->pdev);
 
-       printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name);
+       v4l2_info(&qcam->v4l2_dev, "Connectix Quickcam on %s\n", qcam->pport->name);
 
        if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
                parport_unregister_device(qcam->pdev);
@@ -932,7 +1001,7 @@ static int init_bwqcam(struct parport *port)
        return 0;
 }
 
-static void close_bwqcam(struct qcam_device *qcam)
+static void close_bwqcam(struct qcam *qcam)
 {
        video_unregister_device(&qcam->vdev);
        parport_unregister_device(qcam->pdev);
@@ -983,7 +1052,7 @@ static void bwqcam_detach(struct parport *port)
 {
        int i;
        for (i = 0; i < num_cams; i++) {
-               struct qcam_device *qcam = qcams[i];
+               struct qcam *qcam = qcams[i];
                if (qcam && qcam->pdev->port == port) {
                        qcams[i] = NULL;
                        close_bwqcam(qcam);
diff --git a/drivers/media/video/bw-qcam.h b/drivers/media/video/bw-qcam.h
deleted file mode 100644 (file)
index 8a60c5d..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *     Video4Linux bw-qcam driver
- *
- *     Derived from code..
- */
-
-/******************************************************************
-
-Copyright (C) 1996 by Scott Laird
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL SCOTT LAIRD BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-******************************************************************/
-
-/* One from column A... */
-#define QC_NOTSET 0
-#define QC_UNIDIR 1
-#define QC_BIDIR  2
-#define QC_SERIAL 3
-
-/* ... and one from column B */
-#define QC_ANY          0x00
-#define QC_FORCE_UNIDIR 0x10
-#define QC_FORCE_BIDIR  0x20
-#define QC_FORCE_SERIAL 0x30
-/* in the port_mode member */
-
-#define QC_MODE_MASK    0x07
-#define QC_FORCE_MASK   0x70
-
-#define MAX_HEIGHT 243
-#define MAX_WIDTH 336
-
-/* Bit fields for status flags */
-#define QC_PARAM_CHANGE        0x01 /* Camera status change has occurred */
-
-struct qcam_device {
-       struct video_device vdev;
-       struct pardevice *pdev;
-       struct parport *pport;
-       struct mutex lock;
-       int width, height;
-       int bpp;
-       int mode;
-       int contrast, brightness, whitebal;
-       int port_mode;
-       int transfer_scale;
-       int top, left;
-       int status;
-       unsigned int saved_bits;
-       unsigned long in_use;
-};
index 8f1dd88b32a6c5210269e4d11e8688d4bb9e8fb7..6e4b19698c13fe6212ee08cfd0d9bee7be3cf964 100644 (file)
 #include <linux/mm.h>
 #include <linux/parport.h>
 #include <linux/sched.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
 #include <linux/jiffies.h>
-
+#include <linux/version.h>
+#include <linux/videodev2.h>
 #include <asm/uaccess.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
-struct qcam_device {
+struct qcam {
+       struct v4l2_device v4l2_dev;
        struct video_device vdev;
        struct pardevice *pdev;
        struct parport *pport;
@@ -51,7 +53,6 @@ struct qcam_device {
        int contrast, brightness, whitebal;
        int top, left;
        unsigned int bidirectional;
-       unsigned long in_use;
        struct mutex lock;
 };
 
@@ -68,33 +69,45 @@ struct qcam_device {
 #define QC_DECIMATION_2                2
 #define QC_DECIMATION_4                4
 
-#define BANNER "Colour QuickCam for Video4Linux v0.05"
+#define BANNER "Colour QuickCam for Video4Linux v0.06"
 
 static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
 static int probe = 2;
 static int force_rgb;
 static int video_nr = -1;
 
-static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
+/* FIXME: parport=auto would never have worked, surely? --RR */
+MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
+                         "probe=<0|1|2> for camera detection method\n"
+                         "force_rgb=<0|1> for RGB data format (default BGR)");
+module_param_array(parport, int, NULL, 0);
+module_param(probe, int, 0);
+module_param(force_rgb, bool, 0);
+module_param(video_nr, int, 0);
+
+static struct qcam *qcams[MAX_CAMS];
+static unsigned int num_cams;
+
+static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
 {
        /* note: the QC specs refer to the PCAck pin by voltage, not
           software level.  PC ports have builtin inverters. */
        parport_frob_control(qcam->pport, 8, i ? 8 : 0);
 }
 
-static inline unsigned int qcam_ready1(struct qcam_device *qcam)
+static inline unsigned int qcam_ready1(struct qcam *qcam)
 {
        return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
 }
 
-static inline unsigned int qcam_ready2(struct qcam_device *qcam)
+static inline unsigned int qcam_ready2(struct qcam *qcam)
 {
        return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
 }
 
-static unsigned int qcam_await_ready1(struct qcam_device *qcam,
-                                            int value)
+static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
 {
+       struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
        unsigned long oldjiffies = jiffies;
        unsigned int i;
 
@@ -112,14 +125,15 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
        }
 
        /* Probably somebody pulled the plug out.  Not much we can do. */
-       printk(KERN_ERR "c-qcam: ready1 timeout (%d) %x %x\n", value,
+       v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value,
               parport_read_status(qcam->pport),
               parport_read_control(qcam->pport));
        return 1;
 }
 
-static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
+static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
 {
+       struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
        unsigned long oldjiffies = jiffies;
        unsigned int i;
 
@@ -137,14 +151,14 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
        }
 
        /* Probably somebody pulled the plug out.  Not much we can do. */
-       printk(KERN_ERR "c-qcam: ready2 timeout (%d) %x %x %x\n", value,
+       v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value,
               parport_read_status(qcam->pport),
               parport_read_control(qcam->pport),
               parport_read_data(qcam->pport));
        return 1;
 }
 
-static int qcam_read_data(struct qcam_device *qcam)
+static int qcam_read_data(struct qcam *qcam)
 {
        unsigned int idata;
 
@@ -159,21 +173,22 @@ static int qcam_read_data(struct qcam_device *qcam)
        return idata;
 }
 
-static int qcam_write_data(struct qcam_device *qcam, unsigned int data)
+static int qcam_write_data(struct qcam *qcam, unsigned int data)
 {
+       struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
        unsigned int idata;
 
        parport_write_data(qcam->pport, data);
        idata = qcam_read_data(qcam);
        if (data != idata) {
-               printk(KERN_WARNING "cqcam: sent %x but received %x\n", data,
+               v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
                       idata);
                return 1;
        }
        return 0;
 }
 
-static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned int data)
+static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
 {
        if (qcam_write_data(qcam, cmd))
                return -1;
@@ -182,14 +197,14 @@ static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned
        return 0;
 }
 
-static inline int qcam_get(struct qcam_device *qcam, unsigned int cmd)
+static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
 {
        if (qcam_write_data(qcam, cmd))
                return -1;
        return qcam_read_data(qcam);
 }
 
-static int qc_detect(struct qcam_device *qcam)
+static int qc_detect(struct qcam *qcam)
 {
        unsigned int stat, ostat, i, count = 0;
 
@@ -246,7 +261,7 @@ static int qc_detect(struct qcam_device *qcam)
        return 0;
 }
 
-static void qc_reset(struct qcam_device *qcam)
+static void qc_reset(struct qcam *qcam)
 {
        parport_write_control(qcam->pport, 0xc);
        parport_write_control(qcam->pport, 0x8);
@@ -258,55 +273,55 @@ static void qc_reset(struct qcam_device *qcam)
 /* Reset the QuickCam and program for brightness, contrast,
  * white-balance, and resolution. */
 
-static void qc_setup(struct qcam_device *q)
+static void qc_setup(struct qcam *qcam)
 {
-       qc_reset(q);
+       qc_reset(qcam);
 
        /* Set the brightness. */
-       qcam_set(q, 11, q->brightness);
+       qcam_set(qcam, 11, qcam->brightness);
 
        /* Set the height and width.  These refer to the actual
           CCD area *before* applying the selected decimation.  */
-       qcam_set(q, 17, q->ccd_height);
-       qcam_set(q, 19, q->ccd_width / 2);
+       qcam_set(qcam, 17, qcam->ccd_height);
+       qcam_set(qcam, 19, qcam->ccd_width / 2);
 
        /* Set top and left.  */
-       qcam_set(q, 0xd, q->top);
-       qcam_set(q, 0xf, q->left);
+       qcam_set(qcam, 0xd, qcam->top);
+       qcam_set(qcam, 0xf, qcam->left);
 
        /* Set contrast and white balance.  */
-       qcam_set(q, 0x19, q->contrast);
-       qcam_set(q, 0x1f, q->whitebal);
+       qcam_set(qcam, 0x19, qcam->contrast);
+       qcam_set(qcam, 0x1f, qcam->whitebal);
 
        /* Set the speed.  */
-       qcam_set(q, 45, 2);
+       qcam_set(qcam, 45, 2);
 }
 
 /* Read some bytes from the camera and put them in the buffer.
    nbytes should be a multiple of 3, because bidirectional mode gives
    us three bytes at a time.  */
 
-static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, unsigned int nbytes)
+static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
 {
        unsigned int bytes = 0;
 
-       qcam_set_ack(q, 0);
-       if (q->bidirectional) {
+       qcam_set_ack(qcam, 0);
+       if (qcam->bidirectional) {
                /* It's a bidirectional port */
                while (bytes < nbytes) {
                        unsigned int lo1, hi1, lo2, hi2;
                        unsigned char r, g, b;
 
-                       if (qcam_await_ready2(q, 1))
+                       if (qcam_await_ready2(qcam, 1))
                                return bytes;
-                       lo1 = parport_read_data(q->pport) >> 1;
-                       hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10;
-                       qcam_set_ack(q, 1);
-                       if (qcam_await_ready2(q, 0))
+                       lo1 = parport_read_data(qcam->pport) >> 1;
+                       hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
+                       qcam_set_ack(qcam, 1);
+                       if (qcam_await_ready2(qcam, 0))
                                return bytes;
-                       lo2 = parport_read_data(q->pport) >> 1;
-                       hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10;
-                       qcam_set_ack(q, 0);
+                       lo2 = parport_read_data(qcam->pport) >> 1;
+                       hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
+                       qcam_set_ack(qcam, 0);
                        r = lo1 | ((hi1 & 1) << 7);
                        g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1);
                        b = lo2 | ((hi2 & 1) << 7);
@@ -328,14 +343,14 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, u
                while (bytes < nbytes) {
                        unsigned int hi, lo;
 
-                       if (qcam_await_ready1(q, 1))
+                       if (qcam_await_ready1(qcam, 1))
                                return bytes;
-                       hi = (parport_read_status(q->pport) & 0xf0);
-                       qcam_set_ack(q, 1);
-                       if (qcam_await_ready1(q, 0))
+                       hi = (parport_read_status(qcam->pport) & 0xf0);
+                       qcam_set_ack(qcam, 1);
+                       if (qcam_await_ready1(qcam, 0))
                                return bytes;
-                       lo = (parport_read_status(q->pport) & 0xf0);
-                       qcam_set_ack(q, 0);
+                       lo = (parport_read_status(qcam->pport) & 0xf0);
+                       qcam_set_ack(qcam, 0);
                        /* flip some bits */
                        rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
                        if (i >= 2) {
@@ -361,10 +376,11 @@ get_fragment:
 
 #define BUFSZ  150
 
-static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len)
+static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
 {
+       struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
        unsigned lines, pixelsperline, bitsperxfer;
-       unsigned int is_bi_dir = q->bidirectional;
+       unsigned int is_bi_dir = qcam->bidirectional;
        size_t wantlen, outptr = 0;
        char tmpbuf[BUFSZ];
 
@@ -373,10 +389,10 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
 
        /* Wait for camera to become ready */
        for (;;) {
-               int i = qcam_get(q, 41);
+               int i = qcam_get(qcam, 41);
 
                if (i == -1) {
-                       qc_setup(q);
+                       qc_setup(qcam);
                        return -EIO;
                }
                if ((i & 0x80) == 0)
@@ -384,25 +400,25 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
                schedule();
        }
 
-       if (qcam_set(q, 7, (q->mode | (is_bi_dir ? 1 : 0)) + 1))
+       if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
                return -EIO;
 
-       lines = q->height;
-       pixelsperline = q->width;
+       lines = qcam->height;
+       pixelsperline = qcam->width;
        bitsperxfer = (is_bi_dir) ? 24 : 8;
 
        if (is_bi_dir) {
                /* Turn the port around */
-               parport_data_reverse(q->pport);
+               parport_data_reverse(qcam->pport);
                mdelay(3);
-               qcam_set_ack(q, 0);
-               if (qcam_await_ready1(q, 1)) {
-                       qc_setup(q);
+               qcam_set_ack(qcam, 0);
+               if (qcam_await_ready1(qcam, 1)) {
+                       qc_setup(qcam);
                        return -EIO;
                }
-               qcam_set_ack(q, 1);
-               if (qcam_await_ready1(q, 0)) {
-                       qc_setup(q);
+               qcam_set_ack(qcam, 1);
+               if (qcam_await_ready1(qcam, 0)) {
+                       qc_setup(qcam);
                        return -EIO;
                }
        }
@@ -413,7 +429,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
                size_t t, s;
 
                s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
-               t = qcam_read_bytes(q, tmpbuf, s);
+               t = qcam_read_bytes(qcam, tmpbuf, s);
                if (outptr < len) {
                        size_t sz = len - outptr;
 
@@ -432,10 +448,10 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
        len = outptr;
 
        if (wantlen) {
-               printk(KERN_ERR "qcam: short read.\n");
+               v4l2_err(v4l2_dev, "short read.\n");
                if (is_bi_dir)
-                       parport_data_forward(q->pport);
-               qc_setup(q);
+                       parport_data_forward(qcam->pport);
+               qc_setup(qcam);
                return len;
        }
 
@@ -443,49 +459,49 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
                int l;
 
                do {
-                       l = qcam_read_bytes(q, tmpbuf, 3);
+                       l = qcam_read_bytes(qcam, tmpbuf, 3);
                        cond_resched();
                } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
                if (force_rgb) {
                        if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
-                               printk(KERN_ERR "qcam: bad EOF\n");
+                               v4l2_err(v4l2_dev, "bad EOF\n");
                } else {
                        if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
-                               printk(KERN_ERR "qcam: bad EOF\n");
+                               v4l2_err(v4l2_dev, "bad EOF\n");
                }
-               qcam_set_ack(q, 0);
-               if (qcam_await_ready1(q, 1)) {
-                       printk(KERN_ERR "qcam: no ack after EOF\n");
-                       parport_data_forward(q->pport);
-                       qc_setup(q);
+               qcam_set_ack(qcam, 0);
+               if (qcam_await_ready1(qcam, 1)) {
+                       v4l2_err(v4l2_dev, "no ack after EOF\n");
+                       parport_data_forward(qcam->pport);
+                       qc_setup(qcam);
                        return len;
                }
-               parport_data_forward(q->pport);
+               parport_data_forward(qcam->pport);
                mdelay(3);
-               qcam_set_ack(q, 1);
-               if (qcam_await_ready1(q, 0)) {
-                       printk(KERN_ERR "qcam: no ack to port turnaround\n");
-                       qc_setup(q);
+               qcam_set_ack(qcam, 1);
+               if (qcam_await_ready1(qcam, 0)) {
+                       v4l2_err(v4l2_dev, "no ack to port turnaround\n");
+                       qc_setup(qcam);
                        return len;
                }
        } else {
                int l;
 
                do {
-                       l = qcam_read_bytes(q, tmpbuf, 1);
+                       l = qcam_read_bytes(qcam, tmpbuf, 1);
                        cond_resched();
                } while (l && tmpbuf[0] == 0x7e);
-               l = qcam_read_bytes(q, tmpbuf + 1, 2);
+               l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
                if (force_rgb) {
                        if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
-                               printk(KERN_ERR "qcam: bad EOF\n");
+                               v4l2_err(v4l2_dev, "bad EOF\n");
                } else {
                        if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
-                               printk(KERN_ERR "qcam: bad EOF\n");
+                               v4l2_err(v4l2_dev, "bad EOF\n");
                }
        }
 
-       qcam_write_data(q, 0);
+       qcam_write_data(qcam, 0);
        return len;
 }
 
@@ -493,184 +509,202 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
  *     Video4linux interfacing
  */
 
-static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static int qcam_querycap(struct file *file, void  *priv,
+                                       struct v4l2_capability *vcap)
 {
-       struct video_device *dev = video_devdata(file);
-       struct qcam_device *qcam = (struct qcam_device *)dev;
+       struct qcam *qcam = video_drvdata(file);
 
-       switch (cmd) {
-       case VIDIOCGCAP:
-       {
-               struct video_capability *b = arg;
+       strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
+       strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
+       strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
+       vcap->version = KERNEL_VERSION(0, 0, 3);
+       vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+       return 0;
+}
 
-               strcpy(b->name, "Quickcam");
-               b->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
-               b->channels = 1;
-               b->audios = 0;
-               b->maxwidth = 320;
-               b->maxheight = 240;
-               b->minwidth = 80;
-               b->minheight = 60;
-               return 0;
-       }
-       case VIDIOCGCHAN:
-       {
-               struct video_channel *v = arg;
-
-               if (v->channel != 0)
-                       return -EINVAL;
-               v->flags = 0;
-               v->tuners = 0;
-               /* Good question.. its composite or SVHS so.. */
-               v->type = VIDEO_TYPE_CAMERA;
-               strcpy(v->name, "Camera");
-               return 0;
-       }
-       case VIDIOCSCHAN:
-       {
-               struct video_channel *v = arg;
+static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+       if (vin->index > 0)
+               return -EINVAL;
+       strlcpy(vin->name, "Camera", sizeof(vin->name));
+       vin->type = V4L2_INPUT_TYPE_CAMERA;
+       vin->audioset = 0;
+       vin->tuner = 0;
+       vin->std = 0;
+       vin->status = 0;
+       return 0;
+}
 
-               if (v->channel != 0)
-                       return -EINVAL;
-               return 0;
-       }
-       case VIDIOCGTUNER:
-       {
-               struct video_tuner *v = arg;
-
-               if (v->tuner)
-                       return -EINVAL;
-               memset(v, 0, sizeof(*v));
-               strcpy(v->name, "Format");
-               v->mode = VIDEO_MODE_AUTO;
-               return 0;
+static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+       *inp = 0;
+       return 0;
+}
+
+static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+       return (inp > 0) ? -EINVAL : 0;
+}
+
+static int qcam_queryctrl(struct file *file, void *priv,
+                                       struct v4l2_queryctrl *qc)
+{
+       switch (qc->id) {
+       case V4L2_CID_BRIGHTNESS:
+               return v4l2_ctrl_query_fill(qc, 0, 255, 1, 240);
+       case V4L2_CID_CONTRAST:
+               return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192);
+       case V4L2_CID_GAMMA:
+               return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
        }
-       case VIDIOCSTUNER:
-       {
-               struct video_tuner *v = arg;
-
-               if (v->tuner)
-                       return -EINVAL;
-               if (v->mode != VIDEO_MODE_AUTO)
-                       return -EINVAL;
-               return 0;
+       return -EINVAL;
+}
+
+static int qcam_g_ctrl(struct file *file, void *priv,
+                                       struct v4l2_control *ctrl)
+{
+       struct qcam *qcam = video_drvdata(file);
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ctrl->value = qcam->brightness;
+               break;
+       case V4L2_CID_CONTRAST:
+               ctrl->value = qcam->contrast;
+               break;
+       case V4L2_CID_GAMMA:
+               ctrl->value = qcam->whitebal;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
-       case VIDIOCGPICT:
-       {
-               struct video_picture *p = arg;
-
-               p->colour = 0x8000;
-               p->hue = 0x8000;
-               p->brightness = qcam->brightness << 8;
-               p->contrast = qcam->contrast << 8;
-               p->whiteness = qcam->whitebal << 8;
-               p->depth = 24;
-               p->palette = VIDEO_PALETTE_RGB24;
-               return 0;
+       return ret;
+}
+
+static int qcam_s_ctrl(struct file *file, void *priv,
+                                       struct v4l2_control *ctrl)
+{
+       struct qcam *qcam = video_drvdata(file);
+       int ret = 0;
+
+       mutex_lock(&qcam->lock);
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               qcam->brightness = ctrl->value;
+               break;
+       case V4L2_CID_CONTRAST:
+               qcam->contrast = ctrl->value;
+               break;
+       case V4L2_CID_GAMMA:
+               qcam->whitebal = ctrl->value;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
-       case VIDIOCSPICT:
-       {
-               struct video_picture *p = arg;
-
-               /*
-                *      Sanity check args
-                */
-               if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24)
-                       return -EINVAL;
-
-               /*
-                *      Now load the camera.
-                */
-               qcam->brightness = p->brightness >> 8;
-               qcam->contrast = p->contrast >> 8;
-               qcam->whitebal = p->whiteness >> 8;
-
-               mutex_lock(&qcam->lock);
+       if (ret == 0) {
                parport_claim_or_block(qcam->pdev);
                qc_setup(qcam);
                parport_release(qcam->pdev);
-               mutex_unlock(&qcam->lock);
-               return 0;
        }
-       case VIDIOCSWIN:
-       {
-               struct video_window *vw = arg;
-
-               if (vw->flags)
-                       return -EINVAL;
-               if (vw->clipcount)
-                       return -EINVAL;
-               if (vw->height < 60 || vw->height > 240)
-                       return -EINVAL;
-               if (vw->width < 80 || vw->width > 320)
-                       return -EINVAL;
-
-               qcam->width = 80;
-               qcam->height = 60;
-               qcam->mode = QC_DECIMATION_4;
+       mutex_unlock(&qcam->lock);
+       return ret;
+}
 
-               if (vw->width >= 160 && vw->height >= 120) {
-                       qcam->width = 160;
-                       qcam->height = 120;
-                       qcam->mode = QC_DECIMATION_2;
-               }
-               if (vw->width >= 320 && vw->height >= 240) {
-                       qcam->width = 320;
-                       qcam->height = 240;
-                       qcam->mode = QC_DECIMATION_1;
-               }
-               qcam->mode |= QC_MILLIONS;
-#if 0
-               if (vw->width >= 640 && vw->height >= 480) {
-                       qcam->width = 640;
-                       qcam->height = 480;
-                       qcam->mode = QC_BILLIONS | QC_DECIMATION_1;
-               }
-#endif
-               /* Ok we figured out what to use from our
-                  wide choice */
-               mutex_lock(&qcam->lock);
-               parport_claim_or_block(qcam->pdev);
-               qc_setup(qcam);
-               parport_release(qcam->pdev);
-               mutex_unlock(&qcam->lock);
-               return 0;
-       }
-       case VIDIOCGWIN:
-       {
-               struct video_window *vw = arg;
-               memset(vw, 0, sizeof(*vw));
-               vw->width = qcam->width;
-               vw->height = qcam->height;
-               return 0;
+static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct qcam *qcam = video_drvdata(file);
+       struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+       pix->width = qcam->width;
+       pix->height = qcam->height;
+       pix->pixelformat = V4L2_PIX_FMT_RGB24;
+       pix->field = V4L2_FIELD_NONE;
+       pix->bytesperline = 3 * qcam->width;
+       pix->sizeimage = 3 * qcam->width * qcam->height;
+       /* Just a guess */
+       pix->colorspace = V4L2_COLORSPACE_SRGB;
+       return 0;
+}
+
+static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+       if (pix->height < 60 || pix->width < 80) {
+               pix->height = 60;
+               pix->width = 80;
+       } else if (pix->height < 120 || pix->width < 160) {
+               pix->height = 120;
+               pix->width = 160;
+       } else {
+               pix->height = 240;
+               pix->width = 320;
        }
-       case VIDIOCKEY:
-               return 0;
-       case VIDIOCCAPTURE:
-       case VIDIOCGFBUF:
-       case VIDIOCSFBUF:
-       case VIDIOCGFREQ:
-       case VIDIOCSFREQ:
-       case VIDIOCGAUDIO:
-       case VIDIOCSAUDIO:
-               return -EINVAL;
+       pix->pixelformat = V4L2_PIX_FMT_RGB24;
+       pix->field = V4L2_FIELD_NONE;
+       pix->bytesperline = 3 * pix->width;
+       pix->sizeimage = 3 * pix->width * pix->height;
+       /* Just a guess */
+       pix->colorspace = V4L2_COLORSPACE_SRGB;
+       return 0;
+}
+
+static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct qcam *qcam = video_drvdata(file);
+       struct v4l2_pix_format *pix = &fmt->fmt.pix;
+       int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
+
+       if (ret)
+               return ret;
+       switch (pix->height) {
+       case 60:
+               qcam->mode = QC_DECIMATION_4;
+               break;
+       case 120:
+               qcam->mode = QC_DECIMATION_2;
+               break;
        default:
-               return -ENOIOCTLCMD;
+               qcam->mode = QC_DECIMATION_1;
+               break;
        }
+
+       mutex_lock(&qcam->lock);
+       qcam->mode |= QC_MILLIONS;
+       qcam->height = pix->height;
+       qcam->width = pix->width;
+       parport_claim_or_block(qcam->pdev);
+       qc_setup(qcam);
+       parport_release(qcam->pdev);
+       mutex_unlock(&qcam->lock);
        return 0;
 }
 
-static long qcam_ioctl(struct file *file,
-                     unsigned int cmd, unsigned long arg)
+static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
 {
-       return video_usercopy(file, cmd, arg, qcam_do_ioctl);
+       static struct v4l2_fmtdesc formats[] = {
+               { 0, 0, 0,
+                 "RGB 8:8:8", V4L2_PIX_FMT_RGB24,
+                 { 0, 0, 0, 0 }
+               },
+       };
+       enum v4l2_buf_type type = fmt->type;
+
+       if (fmt->index > 0)
+               return -EINVAL;
+
+       *fmt = formats[fmt->index];
+       fmt->type = type;
+       return 0;
 }
 
 static ssize_t qcam_read(struct file *file, char __user *buf,
                         size_t count, loff_t *ppos)
 {
-       struct video_device *v = video_devdata(file);
-       struct qcam_device *qcam = (struct qcam_device *)v;
+       struct qcam *qcam = video_drvdata(file);
        int len;
 
        mutex_lock(&qcam->lock);
@@ -682,81 +716,80 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
        return len;
 }
 
-static int qcam_exclusive_open(struct file *file)
-{
-       struct video_device *dev = video_devdata(file);
-       struct qcam_device *qcam = (struct qcam_device *)dev;
-
-       return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
-}
-
-static int qcam_exclusive_release(struct file *file)
-{
-       struct video_device *dev = video_devdata(file);
-       struct qcam_device *qcam = (struct qcam_device *)dev;
-
-       clear_bit(0, &qcam->in_use);
-       return 0;
-}
-
-/* video device template */
 static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .open           = qcam_exclusive_open,
-       .release        = qcam_exclusive_release,
-       .ioctl          = qcam_ioctl,
+       .ioctl          = video_ioctl2,
        .read           = qcam_read,
 };
 
-static struct video_device qcam_template = {
-       .name           = "Colour QuickCam",
-       .fops           = &qcam_fops,
-       .release        = video_device_release_empty,
+static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
+       .vidioc_querycap                    = qcam_querycap,
+       .vidioc_g_input                     = qcam_g_input,
+       .vidioc_s_input                     = qcam_s_input,
+       .vidioc_enum_input                  = qcam_enum_input,
+       .vidioc_queryctrl                   = qcam_queryctrl,
+       .vidioc_g_ctrl                      = qcam_g_ctrl,
+       .vidioc_s_ctrl                      = qcam_s_ctrl,
+       .vidioc_enum_fmt_vid_cap            = qcam_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap               = qcam_g_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap               = qcam_s_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap             = qcam_try_fmt_vid_cap,
 };
 
 /* Initialize the QuickCam driver control structure. */
 
-static struct qcam_device *qcam_init(struct parport *port)
+static struct qcam *qcam_init(struct parport *port)
 {
-       struct qcam_device *q;
+       struct qcam *qcam;
+       struct v4l2_device *v4l2_dev;
 
-       q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
-       if (q == NULL)
+       qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
+       if (qcam == NULL)
                return NULL;
 
-       q->pport = port;
-       q->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
+       v4l2_dev = &qcam->v4l2_dev;
+       strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
+
+       if (v4l2_device_register(NULL, v4l2_dev) < 0) {
+               v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+               return NULL;
+       }
+
+       qcam->pport = port;
+       qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
                                          NULL, 0, NULL);
 
-       q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
+       qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
 
-       if (q->pdev == NULL) {
-               printk(KERN_ERR "c-qcam: couldn't register for %s.\n",
-                      port->name);
-               kfree(q);
+       if (qcam->pdev == NULL) {
+               v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
+               kfree(qcam);
                return NULL;
        }
 
-       memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
-
-       mutex_init(&q->lock);
-       q->width = q->ccd_width = 320;
-       q->height = q->ccd_height = 240;
-       q->mode = QC_MILLIONS | QC_DECIMATION_1;
-       q->contrast = 192;
-       q->brightness = 240;
-       q->whitebal = 128;
-       q->top = 1;
-       q->left = 14;
-       return q;
+       strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name));
+       qcam->vdev.v4l2_dev = v4l2_dev;
+       qcam->vdev.fops = &qcam_fops;
+       qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
+       qcam->vdev.release = video_device_release_empty;
+       video_set_drvdata(&qcam->vdev, qcam);
+
+       mutex_init(&qcam->lock);
+       qcam->width = qcam->ccd_width = 320;
+       qcam->height = qcam->ccd_height = 240;
+       qcam->mode = QC_MILLIONS | QC_DECIMATION_1;
+       qcam->contrast = 192;
+       qcam->brightness = 240;
+       qcam->whitebal = 128;
+       qcam->top = 1;
+       qcam->left = 14;
+       return qcam;
 }
 
-static struct qcam_device *qcams[MAX_CAMS];
-static unsigned int num_cams;
-
 static int init_cqcam(struct parport *port)
 {
-       struct qcam_device *qcam;
+       struct qcam *qcam;
+       struct v4l2_device *v4l2_dev;
 
        if (parport[0] != -1) {
                /* The user gave specific instructions */
@@ -777,6 +810,8 @@ static int init_cqcam(struct parport *port)
        if (qcam == NULL)
                return -ENODEV;
 
+       v4l2_dev = &qcam->v4l2_dev;
+
        parport_claim_or_block(qcam->pdev);
 
        qc_reset(qcam);
@@ -793,14 +828,14 @@ static int init_cqcam(struct parport *port)
        parport_release(qcam->pdev);
 
        if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
-               printk(KERN_ERR "Unable to register Colour QuickCam on %s\n",
+               v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n",
                       qcam->pport->name);
                parport_unregister_device(qcam->pdev);
                kfree(qcam);
                return -ENODEV;
        }
 
-       printk(KERN_INFO "%s: Colour QuickCam found on %s\n",
+       v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
               video_device_node_name(&qcam->vdev), qcam->pport->name);
 
        qcams[num_cams++] = qcam;
@@ -808,7 +843,7 @@ static int init_cqcam(struct parport *port)
        return 0;
 }
 
-static void close_cqcam(struct qcam_device *qcam)
+static void close_cqcam(struct qcam *qcam)
 {
        video_unregister_device(&qcam->vdev);
        parport_unregister_device(qcam->pdev);
@@ -833,7 +868,7 @@ static struct parport_driver cqcam_driver = {
 
 static int __init cqcam_init(void)
 {
-       printk(BANNER "\n");
+       printk(KERN_INFO BANNER "\n");
 
        return parport_register_driver(&cqcam_driver);
 }
@@ -852,14 +887,5 @@ MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
 MODULE_DESCRIPTION(BANNER);
 MODULE_LICENSE("GPL");
 
-/* FIXME: parport=auto would never have worked, surely? --RR */
-MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
-                         "probe=<0|1|2> for camera detection method\n"
-                         "force_rgb=<0|1> for RGB data format (default BGR)");
-module_param_array(parport, int, NULL, 0);
-module_param(probe, int, 0);
-module_param(force_rgb, bool, 0);
-module_param(video_nr, int, 0);
-
 module_init(cqcam_init);
 module_exit(cqcam_cleanup);
index b5d7cbf4528ab9d0d455e76ab6ff278493f56ec1..d50d69da387b5d0ea30fb6be335c7fb23523e55b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  ALSA interface to cx18 PCM capture streams
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
  *
  *  Portions of this work were sponsored by ONELAN Limited.
index ef21114309fe61cf4836e96c7c28f0c9fd335f5f..341bddc00b774f5eb5338e224c55d6b8d973416a 100644 (file)
@@ -2,7 +2,7 @@
  *  ALSA mixer controls for the
  *  ALSA interface to cx18 PCM capture streams
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 2d418db000fe6170ffa3a249e4fd18625d84b7dd..ec9238793f6f415fbf660d4b592af1e4431942e7 100644 (file)
@@ -2,7 +2,7 @@
  *  ALSA mixer controls for the
  *  ALSA interface to cx18 PCM capture streams
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 2bd312daeb1e5d6a25521a45e6b289ba256f117e..8f55692db36d278e01191bd3fd2ea9e380c90965 100644 (file)
@@ -2,7 +2,7 @@
  *  ALSA PCM device for the
  *  ALSA interface to cx18 PCM capture streams
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
  *
  *  Portions of this work were sponsored by ONELAN Limited.
index 325662c647a000b8d840d8a26001d5f4f0c72da4..d26e51f94577fac526f8416ce3af303ca87f3048 100644 (file)
@@ -2,7 +2,7 @@
  *  ALSA PCM device for the
  *  ALSA interface to cx18 PCM capture streams
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 88a1cde7540b21957dddf42d97fae1c99ce69642..447da374c9e8312fffc4b7e34bcecb1d068ac96e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  ALSA interface to cx18 PCM capture streams
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 9e30983f2ff632496e2bcf731185956a79542ab6..43d09a24b2624ee936373388e6b195521922c8ff 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from cx25840-audio.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
index 0e5006b14279994d07d14ca2ae4747548c0641f9..a41951cab276a1b6ff68f8fe26c550b6ec9f0869 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from cx25840-core.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
@@ -1021,86 +1021,74 @@ static int cx18_av_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
        return -EINVAL;
 }
 
-static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
-       if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
-               return -EINVAL;
-       return cx18_av_g_sliced_fmt(sd, &fmt->fmt.sliced);
-}
-
-static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
 {
        struct cx18_av_state *state = to_cx18_av_state(sd);
        struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-       struct v4l2_pix_format *pix;
        int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
        int is_50Hz = !(state->std & V4L2_STD_525_60);
 
-       switch (fmt->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               pix = &(fmt->fmt.pix);
+       if (fmt->code != V4L2_MBUS_FMT_FIXED)
+               return -EINVAL;
 
-               Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
-               Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
+       fmt->field = V4L2_FIELD_INTERLACED;
+       fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
 
-               Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
-               Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
+       Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
+       Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
 
-               /*
-                * This adjustment reflects the excess of vactive, set in
-                * cx18_av_std_setup(), above standard values:
-                *
-                * 480 + 1 for 60 Hz systems
-                * 576 + 3 for 50 Hz systems
-                */
-               Vlines = pix->height + (is_50Hz ? 3 : 1);
-
-               /*
-                * Invalid height and width scaling requests are:
-                * 1. width less than 1/16 of the source width
-                * 2. width greater than the source width
-                * 3. height less than 1/8 of the source height
-                * 4. height greater than the source height
-                */
-               if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
-                   (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
-                       CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
-                                    pix->width, pix->height);
-                       return -ERANGE;
-               }
+       Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
+       Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
 
-               HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);
-               VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
-               VSC &= 0x1fff;
+       /*
+        * This adjustment reflects the excess of vactive, set in
+        * cx18_av_std_setup(), above standard values:
+        *
+        * 480 + 1 for 60 Hz systems
+        * 576 + 3 for 50 Hz systems
+        */
+       Vlines = fmt->height + (is_50Hz ? 3 : 1);
 
-               if (pix->width >= 385)
-                       filter = 0;
-               else if (pix->width > 192)
-                       filter = 1;
-               else if (pix->width > 96)
-                       filter = 2;
-               else
-                       filter = 3;
+       /*
+        * Invalid height and width scaling requests are:
+        * 1. width less than 1/16 of the source width
+        * 2. width greater than the source width
+        * 3. height less than 1/8 of the source height
+        * 4. height greater than the source height
+        */
+       if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
+           (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
+               CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
+                            fmt->width, fmt->height);
+               return -ERANGE;
+       }
 
-               CX18_DEBUG_INFO_DEV(sd,
-                                   "decoder set size %dx%d -> scale  %ux%u\n",
-                                   pix->width, pix->height, HSC, VSC);
-
-               /* HSCALE=HSC */
-               cx18_av_write(cx, 0x418, HSC & 0xff);
-               cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
-               cx18_av_write(cx, 0x41a, HSC >> 16);
-               /* VSCALE=VSC */
-               cx18_av_write(cx, 0x41c, VSC & 0xff);
-               cx18_av_write(cx, 0x41d, VSC >> 8);
-               /* VS_INTRLACE=1 VFILT=filter */
-               cx18_av_write(cx, 0x41e, 0x8 | filter);
-               break;
+       HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
+       VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
+       VSC &= 0x1fff;
 
-       default:
-               return -EINVAL;
-       }
+       if (fmt->width >= 385)
+               filter = 0;
+       else if (fmt->width > 192)
+               filter = 1;
+       else if (fmt->width > 96)
+               filter = 2;
+       else
+               filter = 3;
+
+       CX18_DEBUG_INFO_DEV(sd,
+                           "decoder set size %dx%d -> scale  %ux%u\n",
+                           fmt->width, fmt->height, HSC, VSC);
+
+       /* HSCALE=HSC */
+       cx18_av_write(cx, 0x418, HSC & 0xff);
+       cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
+       cx18_av_write(cx, 0x41a, HSC >> 16);
+       /* VSCALE=VSC */
+       cx18_av_write(cx, 0x41c, VSC & 0xff);
+       cx18_av_write(cx, 0x41d, VSC >> 8);
+       /* VS_INTRLACE=1 VFILT=filter */
+       cx18_av_write(cx, 0x41e, 0x8 | filter);
        return 0;
 }
 
@@ -1398,8 +1386,7 @@ static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = {
 static const struct v4l2_subdev_video_ops cx18_av_video_ops = {
        .s_routing = cx18_av_s_video_routing,
        .s_stream = cx18_av_s_stream,
-       .g_fmt = cx18_av_g_fmt,
-       .s_fmt = cx18_av_s_fmt,
+       .s_mbus_fmt = cx18_av_s_mbus_fmt,
 };
 
 static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {
index c106967bdcc3347e5ef1123d7317a44bf16cff59..1956991795e3ab6b20d4a6b7b05ce3ddda5aecc2 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from cx25840-core.h
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
index b9e8cc5d264a4ec12a45ab9bd0fd29bb6b386380..280aa4d22488c658a712e8907823ef0e800358ed 100644 (file)
@@ -2,7 +2,7 @@
  *  cx18 ADEC firmware functions
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
index 74e122b5fc49285ef426b1c63c6bb8f98562f3fa..6b805afe5d20a464aa51a60b2ae74e73a6a498c9 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-cards.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 796e517300ac0f64c950ac86cb9304064ae4c5a0..3e750068f275ed7edb46277370c584d177e83917 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-cards.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 4b4b46544d5a2443c754c0cd9ca4e9966710e5f2..67043c7b452b6f1f0c7a5ec74ebdcc6fa4c55da6 100644 (file)
@@ -297,14 +297,13 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
                if (p.video_encoding != cx->params.video_encoding) {
                        int is_mpeg1 = p.video_encoding ==
                                                V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
-                       struct v4l2_format fmt;
+                       struct v4l2_mbus_framefmt fmt;
 
                        /* fix videodecoder resolution */
-                       fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                       fmt.fmt.pix.width = cx->params.width
-                                               / (is_mpeg1 ? 2 : 1);
-                       fmt.fmt.pix.height = cx->params.height;
-                       v4l2_subdev_call(cx->sd_av, video, s_fmt, &fmt);
+                       fmt.width = cx->params.width / (is_mpeg1 ? 2 : 1);
+                       fmt.height = cx->params.height;
+                       fmt.code = V4L2_MBUS_FMT_FIXED;
+                       v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
                }
                priv.cx = cx;
                priv.s = &cx->streams[id->type];
index c95a86ba33b01b5201799ffb18e1f866c32bf28b..df60f27337cf6d1691db52c9d5000d7b2c35b77a 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-driver.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index b9728e8eee40b7e00cf4dc6d4c0811307045cf01..9bc51a99376bc22231e7c97977d26261de4974b4 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-driver.h
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 0ae2c2e1eab540127317b404979a30217e0cc483..6d19f040d70f7da143741cc231fd56a6b7a4a1ce 100644 (file)
@@ -2,7 +2,7 @@
  *  cx18 functions for DVB support
  *
  *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e12a15020cdab5f62ce8af1b9d9afb5f15702bc5..9f23b90732f2d38ffdfe3e56edb9939501f26654 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-fileops.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 83cd559cc6099ebb7e63886e86bb56e0d6b106ea..1b3fb502e6be5fdb31164407a72f8de96fa9712a 100644 (file)
@@ -2,7 +2,7 @@
  *  cx18 firmware functions
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 86a204b5448e7edd2f1088ee5e3d1b6596b42980..5374aeb0cd2298f263b3216ec76196b528f4b456 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-gpio.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index f9a5ca3566af2fee27cf3b2186674164abc59f0d..4aea2ef88e8d05794e6a07e3a7ba734dc9be1048 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-gpio.h
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index cfa1f289b0f52050e1f2a127bd65248e7ca68a77..809f7d37129c9b475d9cc15c46e7b1fb12e24750 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-i2c.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index ec5b3d7bcc6b0802cca9d7f4366f08d9643758d0..49b9dbd06248c53e0e0388e23e1ceb0104a45ec1 100644 (file)
@@ -2,7 +2,7 @@
  *  cx18 driver PCI memory mapped IO access routines
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 2635b3a8cc96cafea7db8068ae1ab77066f16e01..18974d886cf729e01d777f10a3f2226a936b397d 100644 (file)
@@ -2,7 +2,7 @@
  *  cx18 driver PCI memory mapped IO access routines
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
 /*
  * Readback and retry of MMIO access for reliability:
  * The concept was suggested by Steve Toth <stoth@linuxtv.org>.
- * The implmentation is the fault of Andy Walls <awalls@radix.net>.
+ * The implmentation is the fault of Andy Walls <awalls@md.metrocast.net>.
  *
  * *write* functions are implied to retry the mmio unless suffixed with _noretry
  * *read* functions never retry the mmio (it never helps to do so)
index 2530fc54daaf6bd711b387a86f850ecf6ef47a99..20eaf38ba95976b4a46ae7c785d4e3b63c658071 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-ioctl.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -274,6 +274,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
 {
        struct cx18_open_id *id = fh;
        struct cx18 *cx = id->cx;
+       struct v4l2_mbus_framefmt mbus_fmt;
        int ret;
        int w, h;
 
@@ -293,9 +294,10 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
        if (atomic_read(&cx->ana_capturing) > 0)
                return -EBUSY;
 
-       cx->params.width = w;
-       cx->params.height = h;
-       v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt);
+       mbus_fmt.width = cx->params.width = w;
+       mbus_fmt.height = cx->params.height = h;
+       mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+       v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
        return cx18_g_fmt_vid_cap(file, fh, fmt);
 }
 
index e2ca0d1521165fd210a14e8f535724e0a38d249f..dcb2559ad52050dbaeb0420bff74ed8ebae660f4 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-ioctl.h
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index af2f504eda2b3020efab592ffb834c08087b4d49..80edfe93a3d8948ee13857d439e5574776cfdb99 100644 (file)
@@ -2,7 +2,7 @@
  *  cx18 interrupt handling
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 91f0b5278ef9fb0d5368a350a5e2698f9a5a6dd8..30e7eaf8cb5540007446cb79f0c923caf1d21867 100644 (file)
@@ -2,7 +2,7 @@
  *  cx18 interrupt handling
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 6dcce297752f57f0f1aae616ee5fb7c1debc4da4..956aa190ecca155c8a6c3db78744b94062af30af 100644 (file)
@@ -2,7 +2,7 @@
  *  cx18 mailbox functions
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 33a3491c45374a1128eb8ec8e09e1e91450bc769..077952fcbcca9bf688a61d356dcd9718f3134477 100644 (file)
@@ -2,7 +2,7 @@
  *  cx18 mailbox functions
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index aefc8c8cf3c16f513a897faacf6e4022e1c40ff5..8884537bd62f9bf4685ea1a48c89f970cbb6f8b7 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-queue.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 88a6d34ad3bb8fbf38b35a8bbf1cfe09c13724de..4201ddc16091518b553b0ce0e94282a5e025fb4d 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-queue.h
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 34b4d03c55cda9692668ce05a0a12aa818aa22f7..85cc59637e54f67fa5ef0ad975adbeef4a958b76 100644 (file)
@@ -2,7 +2,7 @@
  *  cx18 System Control Block initialization
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 368f23d08709a6347167c6bf05bc2120057e93bb..08877652e321f8579d350effa6b0531be12f2be1 100644 (file)
@@ -2,7 +2,7 @@
  *  cx18 System Control Block initialization
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index f5c91261b2db08b565f7a94c2e0e38a2930c8315..9045f1ece0ebb35cdb1b85eec68b96cc2344fcfc 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-streams.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 0bff0fa2976370f77dc677673bb93529bcbba647..77412bee59631ae5f80096e1302b83b82243aa2a 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-streams.h
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 2782709b263fa49a7ed72f7a0f5eef9887111b60..e76014561aa782d0a22b725f079dadb2ef03bf58 100644 (file)
@@ -993,6 +993,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        struct cx231xx *dev = fh->dev;
        int rc;
        struct cx231xx_fmt *fmt;
+       struct v4l2_mbus_framefmt mbus_fmt;
 
        rc = check_dev(dev);
        if (rc < 0)
@@ -1026,7 +1027,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        dev->format = fmt;
        get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
 
-       call_all(dev, video, s_fmt, f);
+       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+       call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
 
        /* Set the correct alternate setting for this resolution */
        cx231xx_resolution_set(dev);
index 022b480918cd0da8bfa4d2ccb9d4bb23c6001fb7..2bf44ef10fec2dfb870971535b6f21454ce609b9 100644 (file)
@@ -1113,7 +1113,6 @@ invalid:
 void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
 {
        int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
-       int temporal = p->video_temporal_filter;
 
        /* Stream */
        printk(KERN_INFO "%s: Stream: %s",
@@ -1179,14 +1178,11 @@ void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
                    V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
                p->video_spatial_filter);
 
-       if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
-               temporal = 0;
-
        printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
                prefix,
                cx2341x_menu_item(p,
                        V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
-               temporal);
+               p->video_temporal_filter);
        printk(KERN_INFO
                "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
                prefix,
index 9e1460828b2fb0410de226b7075d526402e13f8a..0a199d774d9b7473c37342f43d3629029d71c83b 100644 (file)
@@ -991,6 +991,8 @@ static int dvb_register(struct cx23885_tsport *port)
        ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
                                        &dev->pci->dev, adapter_nr, 0,
                                        cx23885_dvb_fe_ioctl_override);
+       if (!ret)
+               return ret;
 
        /* init CI & MAC */
        switch (dev->board) {
index 4172cb3874207428556d5d75e99d46e1d5f6a38f..d4746e06451692f8c853bf8c73924c87f6ad70b3 100644 (file)
@@ -365,7 +365,17 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
 
                memset(&info, 0, sizeof(struct i2c_board_info));
                strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-               i2c_new_probed_device(&bus->i2c_adap, &info, addr_list);
+               /*
+                * We can't call i2c_new_probed_device() because it uses
+                * quick writes for probing and the IR receiver device only
+                * replies to reads.
+                */
+               if (i2c_smbus_xfer(&bus->i2c_adap, addr_list[0], 0,
+                                  I2C_SMBUS_READ, 0, I2C_SMBUS_QUICK,
+                                  NULL) >= 0) {
+                       info.addr = addr_list[0];
+                       i2c_new_device(&bus->i2c_adap, &info);
+               }
        }
 
        return bus->i2c_rc;
index 8d306d8bb61cd60260eb6b4906efa851b3328e4e..5de6ba98f7a8383cd3cb3dd7ac83ce690d1f3f29 100644 (file)
@@ -5,7 +5,7 @@
  *
  *  Most of this file is
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *
  *  However, the cx23885_input_{init,fini} functions contained herein are
  *  derived from Linux kernel files linux/media/video/.../...-input.c marked as:
index 3572cb1ecfc2f4557f30502803044a8b16873a89..75ef15d3f5235209365ae49d02fc68b2c24323e1 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Infrared remote control input device
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
index dfb4627fb3402580ff2b13f474e61779b353a3d9..44812ca788992d6a511e12354464df0d85eb64e1 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Various common ioctl() support functions
  *
- *  Copyright (c) 2009 Andy Walls <awalls@radix.net>
+ *  Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 80b0f4923c6a76c9291638532c5cec32c23e546c..315be0ca5a0405045e48053b3784de973a0ddfca 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Various common ioctl() support functions
  *
- *  Copyright (c) 2009 Andy Walls <awalls@radix.net>
+ *  Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 6ae982cc985626fd9edac215117bfbeafe433e2c..9a677eb080af4efb3d58d1dccd63a166a1ef2cdc 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Infrared device support routines - non-input, non-vl42_subdev routines
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
index 9b8a6d5d1ef63ef9198114436ac7a6d07482ed51..0c9d8bda9e2895d1640c96c6b89e16cb95f499ec 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Infrared device support routines - non-input, non-vl42_subdev routines
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
index 543b854f6a620498e37e1d9dbf3b081cfddf309b..4e44dcda38756e298aa2da930907cde71ae5a113 100644 (file)
@@ -976,6 +976,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 {
        struct cx23885_fh *fh = priv;
        struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
+       struct v4l2_mbus_framefmt mbus_fmt;
        int err;
 
        dprintk(2, "%s()\n", __func__);
@@ -989,7 +990,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        fh->vidq.field = f->fmt.pix.field;
        dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
                fh->width, fh->height, fh->vidq.field);
-       call_all(dev, video, s_fmt, f);
+       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+       call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
        return 0;
 }
 
index ad728d767d699eba750ebbe5b65915d857a42b50..f63d378257a76ccc733fe953b513e0e6e84e8b62 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  CX23888 Integrated Consumer Infrared Controller
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
index 3d446f9eb94bd2bfce686e488b8b6cb37c91428a..d2de41caaf1d6e902354adfacb6e8611cc7948d3 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  CX23888 Integrated Consumer Infrared Controller
  *
- *  Copyright (C) 2009  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
index 8b6fb35443769140ac04de0d241765f47f9974be..bb4872b2ceb0d0a6455d792f84ddfa9217c0014c 100644 (file)
@@ -1014,75 +1014,59 @@ static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 
 /* ----------------------------------------------------------------------- */
 
-static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
-       switch (fmt->type) {
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-               return cx25840_g_sliced_fmt(sd, &fmt->fmt.sliced);
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
 {
        struct cx25840_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct v4l2_pix_format *pix;
        int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
        int is_50Hz = !(state->std & V4L2_STD_525_60);
 
-       switch (fmt->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               pix = &(fmt->fmt.pix);
-
-               Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
-               Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
-
-               Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
-               Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
+       if (fmt->code != V4L2_MBUS_FMT_FIXED)
+               return -EINVAL;
 
-               Vlines = pix->height + (is_50Hz ? 4 : 7);
+       fmt->field = V4L2_FIELD_INTERLACED;
+       fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
 
-               if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
-                   (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
-                       v4l_err(client, "%dx%d is not a valid size!\n",
-                                   pix->width, pix->height);
-                       return -ERANGE;
-               }
+       Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
+       Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
 
-               HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);
-               VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
-               VSC &= 0x1fff;
+       Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
+       Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
 
-               if (pix->width >= 385)
-                       filter = 0;
-               else if (pix->width > 192)
-                       filter = 1;
-               else if (pix->width > 96)
-                       filter = 2;
-               else
-                       filter = 3;
-
-               v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale  %ux%u\n",
-                           pix->width, pix->height, HSC, VSC);
-
-               /* HSCALE=HSC */
-               cx25840_write(client, 0x418, HSC & 0xff);
-               cx25840_write(client, 0x419, (HSC >> 8) & 0xff);
-               cx25840_write(client, 0x41a, HSC >> 16);
-               /* VSCALE=VSC */
-               cx25840_write(client, 0x41c, VSC & 0xff);
-               cx25840_write(client, 0x41d, VSC >> 8);
-               /* VS_INTRLACE=1 VFILT=filter */
-               cx25840_write(client, 0x41e, 0x8 | filter);
-               break;
+       Vlines = fmt->height + (is_50Hz ? 4 : 7);
 
-       default:
-               return -EINVAL;
+       if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
+                       (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
+               v4l_err(client, "%dx%d is not a valid size!\n",
+                               fmt->width, fmt->height);
+               return -ERANGE;
        }
 
+       HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
+       VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
+       VSC &= 0x1fff;
+
+       if (fmt->width >= 385)
+               filter = 0;
+       else if (fmt->width > 192)
+               filter = 1;
+       else if (fmt->width > 96)
+               filter = 2;
+       else
+               filter = 3;
+
+       v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale  %ux%u\n",
+                       fmt->width, fmt->height, HSC, VSC);
+
+       /* HSCALE=HSC */
+       cx25840_write(client, 0x418, HSC & 0xff);
+       cx25840_write(client, 0x419, (HSC >> 8) & 0xff);
+       cx25840_write(client, 0x41a, HSC >> 16);
+       /* VSCALE=VSC */
+       cx25840_write(client, 0x41c, VSC & 0xff);
+       cx25840_write(client, 0x41d, VSC >> 8);
+       /* VS_INTRLACE=1 VFILT=filter */
+       cx25840_write(client, 0x41e, 0x8 | filter);
        return 0;
 }
 
@@ -1627,8 +1611,7 @@ static const struct v4l2_subdev_audio_ops cx25840_audio_ops = {
 
 static const struct v4l2_subdev_video_ops cx25840_video_ops = {
        .s_routing = cx25840_s_video_routing,
-       .g_fmt = cx25840_g_fmt,
-       .s_fmt = cx25840_s_fmt,
+       .s_mbus_fmt = cx25840_s_mbus_fmt,
        .s_stream = cx25840_s_stream,
 };
 
index ee1ca39db06ad684758dc4da0bfa8b35aa8e1f56..fb39f11845583a86dcb463745d66d498bc873efe 100644 (file)
@@ -188,10 +188,24 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
                        0x18, 0x6b, 0x71,
                        I2C_CLIENT_END
                };
+               const unsigned short *addrp;
 
                memset(&info, 0, sizeof(struct i2c_board_info));
                strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-               i2c_new_probed_device(&core->i2c_adap, &info, addr_list);
+               /*
+                * We can't call i2c_new_probed_device() because it uses
+                * quick writes for probing and at least some R receiver
+                * devices only reply to reads.
+                */
+               for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {
+                       if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
+                                          I2C_SMBUS_READ, 0,
+                                          I2C_SMBUS_QUICK, NULL) >= 0) {
+                               info.addr = *addrp;
+                               i2c_new_device(&core->i2c_adap, &info);
+                               break;
+                       }
+               }
        }
        return core->i2c_rc;
 }
index 331e1cac427221ba39f1002fa625a913da35363e..44c63cbd6dda8da1dcdc1375c94db856e934b4d4 100644 (file)
@@ -1186,8 +1186,7 @@ int em28xx_register_extension(struct em28xx_ops *ops)
        mutex_lock(&em28xx_devlist_mutex);
        list_add_tail(&ops->next, &em28xx_extension_devlist);
        list_for_each_entry(dev, &em28xx_devlist, devlist) {
-               if (dev)
-                       ops->init(dev);
+               ops->init(dev);
        }
        printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
        mutex_unlock(&em28xx_devlist_mutex);
@@ -1201,10 +1200,8 @@ void em28xx_unregister_extension(struct em28xx_ops *ops)
 
        mutex_lock(&em28xx_devlist_mutex);
        list_for_each_entry(dev, &em28xx_devlist, devlist) {
-               if (dev)
-                       ops->fini(dev);
+               ops->fini(dev);
        }
-
        printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
        list_del(&ops->next);
        mutex_unlock(&em28xx_devlist_mutex);
index 785eeb4c20144573416c44f8b970198e74730ba6..95354a339e3d3aabd100fd11d26dc893c7e9bee4 100644 (file)
@@ -1453,9 +1453,7 @@ static const struct usb_device_id device_table[] __devinitconst = {
        {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
        {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
        {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
-#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
        {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
-#endif
        {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
        {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
index bb923efb75bd5c0ddd6cec17633a256f32973557..176c5b3d5e6f9096df04276a56995d3ce08684e7 100644 (file)
@@ -3022,16 +3022,18 @@ static const __devinitdata struct usb_device_id device_table[] = {
 /*     {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
 /*     {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
 /*     {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */
+       {USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},
        {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},
 /*     {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */
 /*     {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
+/*     {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
        {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
        {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
        {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
 #endif
        {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)},      /*sn9c128*/
-/*     {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, P1030xC)}, */
+/*     {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)}, * / GC0305*/
 /*     {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
        {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)},      /*sn9c128*/
        {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)},      /*sn9c128*/
@@ -3058,6 +3060,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
        {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
        {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
        {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)},     /*sn9c120b*/
+                                               /* or GC0305 / GC0307 */
        {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)},     /*sn9c120b*/
        {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)},      /*sn9c120b*/
        {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)},    /*sn9c120b*/
index 7cfccfd1b870fc6f202c9b6cbf6f843ab5bec7b0..c338f3f62e777abd0950d123c11338159a6788f0 100644 (file)
@@ -366,7 +366,7 @@ static int hdpvr_open(struct file *file)
 
        dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file));
        if (!dev) {
-               v4l2_err(&dev->v4l2_dev, "open failing with with ENODEV\n");
+               pr_err("open failing with with ENODEV\n");
                retval = -ENODEV;
                goto err;
        }
index b59475bfc243990a7397281ca90ac2c2b9170402..b588e30cbcf02bfa79fef54c09e3134a536bb730 100644 (file)
@@ -267,13 +267,13 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
                if (p.video_encoding != itv->params.video_encoding) {
                        int is_mpeg1 = p.video_encoding ==
                                V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
-                       struct v4l2_format fmt;
+                       struct v4l2_mbus_framefmt fmt;
 
                        /* fix videodecoder resolution */
-                       fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                       fmt.fmt.pix.width = itv->params.width / (is_mpeg1 ? 2 : 1);
-                       fmt.fmt.pix.height = itv->params.height;
-                       v4l2_subdev_call(itv->sd_video, video, s_fmt, &fmt);
+                       fmt.width = itv->params.width / (is_mpeg1 ? 2 : 1);
+                       fmt.height = itv->params.height;
+                       fmt.code = V4L2_MBUS_FMT_FIXED;
+                       v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
                }
                err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p);
                if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt)
index abf410943cc9f54cdf2047597c07117f1408f102..3c2cc270ccd548bd455b69073f3f584f6944650a 100644 (file)
@@ -823,6 +823,12 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
 
        IVTV_DEBUG_FILE("close() of %s\n", s->name);
 
+       if (id->type == IVTV_DEC_STREAM_TYPE_YUV &&
+               test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) {
+               /* Restore registers we've changed & clean up any mess */
+               ivtv_yuv_close(itv);
+       }
+
        /* Stop decoding */
        if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
                IVTV_DEBUG_INFO("close stopping decode\n");
@@ -832,10 +838,7 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
        }
        clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
        clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
-       if (id->type == IVTV_DEC_STREAM_TYPE_YUV && test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) {
-               /* Restore registers we've changed & clean up any mess we've made */
-               ivtv_yuv_close(itv);
-       }
+
        if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames)
                itv->output_mode = OUT_NONE;
 
index fa9f0d958f96c25fd682d2a2fd65e07ac9c724b9..11ac2fa33ef7153855ff7f17f0a2a35a11e661df 100644 (file)
@@ -569,6 +569,7 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
        struct ivtv_open_id *id = fh;
        struct ivtv *itv = id->itv;
        struct cx2341x_mpeg_params *p = &itv->params;
+       struct v4l2_mbus_framefmt mbus_fmt;
        int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
        int w = fmt->fmt.pix.width;
        int h = fmt->fmt.pix.height;
@@ -586,7 +587,10 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
        p->height = h;
        if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
                fmt->fmt.pix.width /= 2;
-       v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
+       mbus_fmt.width = fmt->fmt.pix.width;
+       mbus_fmt.height = h;
+       mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+       v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
        return ivtv_g_fmt_vid_cap(file, fh, fmt);
 }
 
index de4288cc188933d6e4100fb162dcab9099a14238..9ecacab4b89b3a63c601d12c3ea6ba1862f115e3 100644 (file)
@@ -618,12 +618,17 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
        struct ivtv *itv = s->itv;
        struct cx2341x_mpeg_params *p = &itv->params;
        int datatype;
+       u16 width;
+       u16 height;
 
        if (s->vdev == NULL)
                return -EINVAL;
 
        IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
 
+       width = p->width;
+       height = p->height;
+
        /* set audio mode to left/stereo  for dual/stereo mode. */
        ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
 
@@ -646,7 +651,14 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
           2 = yuv_from_host */
        switch (s->type) {
        case IVTV_DEC_STREAM_TYPE_YUV:
-               datatype = itv->output_mode == OUT_PASSTHROUGH ? 1 : 2;
+               if (itv->output_mode == OUT_PASSTHROUGH) {
+                       datatype = 1;
+               } else {
+                       /* Fake size to avoid switching video standard */
+                       datatype = 2;
+                       width = 720;
+                       height = itv->is_out_50hz ? 576 : 480;
+               }
                IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype);
                break;
        case IVTV_DEC_STREAM_TYPE_MPG:
@@ -655,9 +667,13 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
                break;
        }
        if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
-                       p->width, p->height, p->audio_properties)) {
+                       width, height, p->audio_properties)) {
                IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
        }
+
+       /* Decoder sometimes dies here, so wait a moment */
+       ivtv_msleep_timeout(10, 0);
+
        return 0;
 }
 
@@ -697,6 +713,9 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
        /* start playback */
        ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0);
 
+       /* Let things settle before we actually start */
+       ivtv_msleep_timeout(10, 0);
+
        /* Clear the following Interrupt mask bits for decoding */
        ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
        IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask);
index 49e1a283ed3649ec8cf55e19663e24628652d89c..9ff3425891edc7f678452317d33351ab80a4034c 100644 (file)
@@ -1066,7 +1066,11 @@ static int ivtvfb_init_io(struct ivtv *itv)
        }
        mutex_unlock(&itv->serialize_lock);
 
-       ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size);
+       if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
+                                       &oi->video_buffer_size) < 0) {
+               IVTVFB_ERR("Firmware failed to respond\n");
+               return -EIO;
+       }
 
        /* The osd buffer size depends on the number of video buffers allocated
           on the PVR350 itself. For now we'll hardcode the smallest osd buffer
@@ -1158,8 +1162,11 @@ static int ivtvfb_init_card(struct ivtv *itv)
        }
 
        /* Find & setup the OSD buffer */
-       if ((rc = ivtvfb_init_io(itv)))
+       rc = ivtvfb_init_io(itv);
+       if (rc) {
+               ivtvfb_release_buffers(itv);
                return rc;
+       }
 
        /* Set the startup video mode information */
        if ((rc = ivtvfb_init_vidmode(itv))) {
@@ -1210,6 +1217,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p)
 {
        struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
        struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
+       struct osd_info *oi = itv->osd_info;
 
        if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
                if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
@@ -1218,7 +1226,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p)
                        return 0;
                }
                IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
-               ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info);
+               ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
                ivtvfb_release_buffers(itv);
                itv->osd_video_pbase = 0;
        }
index b62c0bd3f8ea013de803ceac7f3f25f1c7a9bb57..79f096ddcf5def01671ef05af5fe8abcad4c8878 100644 (file)
@@ -701,13 +701,13 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
 #endif
 };
 
-static int mt9m001_enum_fmt(struct v4l2_subdev *sd, int index,
+static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                            enum v4l2_mbus_pixelcode *code)
 {
        struct i2c_client *client = sd->priv;
        struct mt9m001 *mt9m001 = to_mt9m001(client);
 
-       if ((unsigned int)index >= mt9m001->num_fmts)
+       if (index >= mt9m001->num_fmts)
                return -EINVAL;
 
        *code = mt9m001->fmts[index].code;
@@ -785,7 +785,6 @@ static int mt9m001_probe(struct i2c_client *client,
        ret = mt9m001_video_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(mt9m001);
        }
 
@@ -799,7 +798,6 @@ static int mt9m001_remove(struct i2c_client *client)
 
        icd->ops = NULL;
        mt9m001_video_remove(icd);
-       i2c_set_clientdata(client, NULL);
        client->driver = NULL;
        kfree(mt9m001);
 
index d35f536f9fc37fd6729211d9610adbfa2334c77e..fbd0fc794720cb21ef56345315a382d0f3263e27 100644 (file)
@@ -999,10 +999,10 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
 #endif
 };
 
-static int mt9m111_enum_fmt(struct v4l2_subdev *sd, int index,
+static int mt9m111_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                            enum v4l2_mbus_pixelcode *code)
 {
-       if ((unsigned int)index >= ARRAY_SIZE(mt9m111_colour_fmts))
+       if (index >= ARRAY_SIZE(mt9m111_colour_fmts))
                return -EINVAL;
 
        *code = mt9m111_colour_fmts[index].code;
@@ -1068,7 +1068,6 @@ static int mt9m111_probe(struct i2c_client *client,
        ret = mt9m111_video_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(mt9m111);
        }
 
@@ -1081,7 +1080,6 @@ static int mt9m111_remove(struct i2c_client *client)
        struct soc_camera_device *icd = client->dev.platform_data;
 
        icd->ops = NULL;
-       i2c_set_clientdata(client, NULL);
        client->driver = NULL;
        kfree(mt9m111);
 
index 78b4e091d2d5f527dd76db13a072bb339289fa84..a9a28b2142359adcce64d15ed0cc4a64a8ab71e1 100644 (file)
@@ -798,7 +798,7 @@ static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
 #endif
 };
 
-static int mt9t031_enum_fmt(struct v4l2_subdev *sd, int index,
+static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                            enum v4l2_mbus_pixelcode *code)
 {
        if (index)
@@ -883,7 +883,6 @@ static int mt9t031_probe(struct i2c_client *client,
        if (ret) {
                if (icd)
                        icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(mt9t031);
        }
 
@@ -897,7 +896,6 @@ static int mt9t031_remove(struct i2c_client *client)
 
        if (icd)
                icd->ops = NULL;
-       i2c_set_clientdata(client, NULL);
        client->driver = NULL;
        kfree(mt9t031);
 
index 7438f8d775ba7fa09fb32f9ad2f0a8934606afb5..e4bf1db9a87b4d978eaad6646c1fed2b1076cf70 100644 (file)
@@ -1017,10 +1017,10 @@ static int mt9t112_try_fmt(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int mt9t112_enum_fmt(struct v4l2_subdev *sd, int index,
+static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                           enum v4l2_mbus_pixelcode *code)
 {
-       if ((unsigned int)index >= ARRAY_SIZE(mt9t112_cfmts))
+       if (index >= ARRAY_SIZE(mt9t112_cfmts))
                return -EINVAL;
 
        *code = mt9t112_cfmts[index].code;
@@ -1119,7 +1119,6 @@ static int mt9t112_probe(struct i2c_client *client,
        ret = mt9t112_camera_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(priv);
        }
 
@@ -1132,7 +1131,6 @@ static int mt9t112_remove(struct i2c_client *client)
        struct soc_camera_device *icd = client->dev.platform_data;
 
        icd->ops = NULL;
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
        return 0;
 }
index 72e55be0b4abae5fdc59651117613e84c6f4e348..f5e778d5ca9fdb859754b8d3f99601833029d973 100644 (file)
@@ -392,27 +392,25 @@ static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
        return 0;
 }
 
-static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
+static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+                                       enum v4l2_mbus_pixelcode *code)
 {
-       if (fmt->index > 0)
+       if (index > 0)
                return -EINVAL;
 
-       fmt->flags = 0;
-       strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG");
-       fmt->pixelformat = V4L2_PIX_FMT_SGRBG8;
-
+       *code = V4L2_MBUS_FMT_SGRBG8_1X8;
        return 0;
 }
 
-static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
 {
-       struct v4l2_pix_format *pix = &fmt->fmt.pix;
-
-       if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8)
+       if (fmt->code != V4L2_MBUS_FMT_SGRBG8_1X8)
                return -EINVAL;
 
-       v4l_bound_align_image(&pix->width, 48, 639, 1,
-                             &pix->height, 32, 480, 1, 0);
+       v4l_bound_align_image(&fmt->width, 48, 639, 1,
+                             &fmt->height, 32, 480, 1, 0);
+       fmt->field = V4L2_FIELD_NONE;
+       fmt->colorspace = V4L2_COLORSPACE_SRGB;
 
        return 0;
 }
@@ -455,18 +453,17 @@ static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
        return 0;
 }
 
-static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
 {
-       struct v4l2_pix_format *pix = &fmt->fmt.pix;
        struct mt9v011 *core = to_mt9v011(sd);
        int rc;
 
-       rc = mt9v011_try_fmt(sd, fmt);
+       rc = mt9v011_try_mbus_fmt(sd, fmt);
        if (rc < 0)
                return -EINVAL;
 
-       core->width = pix->width;
-       core->height = pix->height;
+       core->width = fmt->width;
+       core->height = fmt->height;
 
        set_res(sd);
 
@@ -549,9 +546,9 @@ static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
 };
 
 static const struct v4l2_subdev_video_ops mt9v011_video_ops = {
-       .enum_fmt = mt9v011_enum_fmt,
-       .try_fmt = mt9v011_try_fmt,
-       .s_fmt = mt9v011_s_fmt,
+       .enum_mbus_fmt = mt9v011_enum_mbus_fmt,
+       .try_mbus_fmt = mt9v011_try_mbus_fmt,
+       .s_mbus_fmt = mt9v011_s_mbus_fmt,
        .g_parm = mt9v011_g_parm,
        .s_parm = mt9v011_s_parm,
 };
index e5bae4c9393b8b9e3d4a0c8acbcf770d627fe3bc..e7cd23cd63941ecb3380243f623960cf91c8ea31 100644 (file)
@@ -838,13 +838,13 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
 #endif
 };
 
-static int mt9v022_enum_fmt(struct v4l2_subdev *sd, int index,
+static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                            enum v4l2_mbus_pixelcode *code)
 {
        struct i2c_client *client = sd->priv;
        struct mt9v022 *mt9v022 = to_mt9v022(client);
 
-       if ((unsigned int)index >= mt9v022->num_fmts)
+       if (index >= mt9v022->num_fmts)
                return -EINVAL;
 
        *code = mt9v022->fmts[index].code;
@@ -920,7 +920,6 @@ static int mt9v022_probe(struct i2c_client *client,
        ret = mt9v022_video_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(mt9v022);
        }
 
@@ -934,7 +933,6 @@ static int mt9v022_remove(struct i2c_client *client)
 
        icd->ops = NULL;
        mt9v022_video_remove(icd);
-       i2c_set_clientdata(client, NULL);
        client->driver = NULL;
        kfree(mt9v022);
 
index d477e3058002c27f996c445b1980e2a4e1ae24ea..a9be14c239124a06185c3ff6c43af44bb47d4f83 100644 (file)
@@ -672,7 +672,7 @@ static bool mx3_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
                 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
 }
 
-static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx,
+static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
                                  struct soc_camera_format_xlate *xlate)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
@@ -689,7 +689,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx,
        fmt = soc_mbus_get_fmtdesc(code);
        if (!fmt) {
                dev_err(icd->dev.parent,
-                       "Invalid format code #%d: %d\n", idx, code);
+                       "Invalid format code #%u: %d\n", idx, code);
                return 0;
        }
 
index 4c0ab499228bd5d6a559932b5ef63e6e9646c5a1..e7db0554949a943fff6d3f6e1221064916b7acb1 100644 (file)
@@ -2371,12 +2371,11 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
 
        for (k = 0; k < pdev->num_resources; k++) {
 
-               vout = kmalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
+               vout = kzalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
                if (!vout) {
                        dev_err(&pdev->dev, ": could not allocate memory\n");
                        return -ENOMEM;
                }
-               memset(vout, 0, sizeof(struct omap_vout_device));
 
                vout->vid = k;
                vid_dev->vouts[k] = vout;
index 7f8ece30c77ba790cb38c314783544a0de0e162d..34034a710214e39b30f6f194f5cde31383aa9636 100644 (file)
@@ -1092,10 +1092,10 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = {
 #endif
 };
 
-static int ov772x_enum_fmt(struct v4l2_subdev *sd, int index,
+static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                           enum v4l2_mbus_pixelcode *code)
 {
-       if ((unsigned int)index >= ARRAY_SIZE(ov772x_cfmts))
+       if (index >= ARRAY_SIZE(ov772x_cfmts))
                return -EINVAL;
 
        *code = ov772x_cfmts[index].code;
@@ -1159,7 +1159,6 @@ static int ov772x_probe(struct i2c_client *client,
        ret = ov772x_video_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(priv);
        }
 
@@ -1172,7 +1171,6 @@ static int ov772x_remove(struct i2c_client *client)
        struct soc_camera_device *icd = client->dev.platform_data;
 
        icd->ops = NULL;
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
        return 0;
 }
index 36599a65f54851759f47a5a412bd5fdc629b8e1f..7ce9e05b47815c764baa56d087dab3d47b4b228d 100644 (file)
@@ -614,10 +614,10 @@ static int ov9640_try_fmt(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int ov9640_enum_fmt(struct v4l2_subdev *sd, int index,
+static int ov9640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                           enum v4l2_mbus_pixelcode *code)
 {
-       if ((unsigned int)index >= ARRAY_SIZE(ov9640_codes))
+       if (index >= ARRAY_SIZE(ov9640_codes))
                return -EINVAL;
 
        *code = ov9640_codes[index];
@@ -783,7 +783,6 @@ static int ov9640_probe(struct i2c_client *client,
 
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(priv);
        }
 
@@ -794,7 +793,6 @@ static int ov9640_remove(struct i2c_client *client)
 {
        struct ov9640_priv *priv = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
        return 0;
 }
index 6bc16c13ccef7423558e48bb58d8ad85273c0241..3092abfd66a21e69113728127ad9aaf9e64d79c1 100644 (file)
@@ -117,6 +117,7 @@ static const struct pvr2_device_desc pvr2_device_24xxx = {
 static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = {
        { .module_id = PVR2_CLIENT_ID_CX25840 },
        { .module_id = PVR2_CLIENT_ID_TUNER },
+       { .module_id = PVR2_CLIENT_ID_DEMOD },
 };
 
 static const struct pvr2_device_desc pvr2_device_gotview_2 = {
index e5b9594eb5f6266acbdbe757740c5be47b5e7d4b..273c8d4b3853b1c7b34cc7db301506d666280a07 100644 (file)
@@ -177,6 +177,11 @@ struct pvr2_device_desc {
        unsigned int flag_has_composite:1;     /* Has composite input */
        unsigned int flag_has_svideo:1;        /* Has s-video input */
        unsigned int flag_fx2_16kb:1;          /* 16KB FX2 firmware OK here */
+
+       /* If this driver is considered experimental, i.e. not all aspects
+          are working correctly and/or it is untested, mark that fact
+          with this flag. */
+       unsigned int flag_is_experimental:1;
 };
 
 extern struct usb_device_id pvr2_device_table[];
index 301ef197d038140008b4b5c59290ef467fe4f76d..70ea578d6266cfba9540417aa63ced74ab45d2a4 100644 (file)
@@ -2459,6 +2459,19 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                   hdw,hdw_desc->description);
        pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s",
                hdw_desc->description);
+       if (hdw_desc->flag_is_experimental) {
+               pvr2_trace(PVR2_TRACE_INFO, "**********");
+               pvr2_trace(PVR2_TRACE_INFO,
+                          "WARNING: Support for this device (%s) is"
+                          " experimental.", hdw_desc->description);
+               pvr2_trace(PVR2_TRACE_INFO,
+                          "Important functionality might not be"
+                          " entirely working.");
+               pvr2_trace(PVR2_TRACE_INFO,
+                          "Please consider contacting the driver author to"
+                          " help with further stabilization of the driver.");
+               pvr2_trace(PVR2_TRACE_INFO, "**********");
+       }
        if (!hdw) goto fail;
 
        init_timer(&hdw->quiescent_timer);
@@ -3056,14 +3069,14 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw)
        }
 
        if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) {
-               struct v4l2_format fmt;
+               struct v4l2_mbus_framefmt fmt;
                memset(&fmt, 0, sizeof(fmt));
-               fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               fmt.fmt.pix.width = hdw->res_hor_val;
-               fmt.fmt.pix.height = hdw->res_ver_val;
+               fmt.width = hdw->res_hor_val;
+               fmt.height = hdw->res_ver_val;
+               fmt.code = V4L2_MBUS_FMT_FIXED;
                pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)",
-                          fmt.fmt.pix.width, fmt.fmt.pix.height);
-               v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt);
+                          fmt.width, fmt.height);
+               v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_mbus_fmt, &fmt);
        }
 
        if (hdw->srate_dirty || hdw->force_dirty) {
@@ -4084,12 +4097,20 @@ void pvr2_hdw_device_reset(struct pvr2_hdw *hdw)
 
 void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
 {
-       char da[1];
+       char *da;
        unsigned int pipe;
        int ret;
 
        if (!hdw->usb_dev) return;
 
+       da = kmalloc(16, GFP_KERNEL);
+
+       if (da == NULL) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Unable to allocate memory to control CPU reset");
+               return;
+       }
+
        pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val);
 
        da[0] = val ? 0x01 : 0x00;
@@ -4103,6 +4124,8 @@ void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
                           "cpureset_assert(%d) error=%d",val,ret);
                pvr2_hdw_render_useless(hdw);
        }
+
+       kfree(da);
 }
 
 
index eeacd0f67855d118b49aa8ad5cd4a11bfe9d3ce6..2254194aad579c201475784f7c27a51e7be6791d 100644 (file)
@@ -153,12 +153,12 @@ static void __exit pvr_exit(void)
 
        usb_deregister(&pvr_driver);
 
+       pvr2_context_global_done();
+
 #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
        pvr2_sysfs_class_destroy(class_ptr);
 #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
 
-       pvr2_context_global_done();
-
        pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete");
 }
 
index 71f50565f637c804f19fac089cf62af55134bf55..3d7e5aab547fdf0c15e680c5e26aa8d98e46eaa5 100644 (file)
@@ -74,7 +74,7 @@ struct pvr2_sysfs_ctl_item {
        int ctl_id;
        struct pvr2_sysfs *chptr;
        struct pvr2_sysfs_ctl_item *item_next;
-       struct attribute *attr_gen[7];
+       struct attribute *attr_gen[8];
        struct attribute_group grp;
        int created_ok;
        char name[80];
@@ -511,6 +511,7 @@ static void pvr2_sysfs_release(struct device *class_dev)
 
 static void class_dev_destroy(struct pvr2_sysfs *sfp)
 {
+       struct device *dev;
        if (!sfp->class_dev) return;
 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
        pvr2_sysfs_tear_down_debugifc(sfp);
@@ -542,6 +543,9 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp)
        }
        pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
        dev_set_drvdata(sfp->class_dev, NULL);
+       dev = sfp->class_dev->parent;
+       sfp->class_dev->parent = NULL;
+       put_device(dev);
        device_unregister(sfp->class_dev);
        sfp->class_dev = NULL;
 }
@@ -631,10 +635,11 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
 
        class_dev->class = &class_ptr->class;
+
        dev_set_name(class_dev, "%s",
                     pvr2_hdw_get_device_identifier(sfp->channel.hdw));
 
-       class_dev->parent = &usb_dev->dev;
+       class_dev->parent = get_device(&usb_dev->dev);
 
        sfp->class_dev = class_dev;
        dev_set_drvdata(class_dev, sfp);
@@ -775,7 +780,8 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
        struct pvr2_sysfs_class *clp;
        clp = kzalloc(sizeof(*clp),GFP_KERNEL);
        if (!clp) return clp;
-       pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp);
+       pvr2_sysfs_trace("Creating and registering pvr2_sysfs_class id=%p",
+                        clp);
        clp->class.name = "pvrusb2";
        clp->class.class_release = pvr2_sysfs_class_release;
        clp->class.dev_release = pvr2_sysfs_release;
@@ -791,6 +797,7 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
 
 void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
 {
+       pvr2_sysfs_trace("Unregistering pvr2_sysfs_class id=%p", clp);
        class_unregister(&clp->class);
 }
 
index 5ffa0d2b0b0d957c9b94d118110078f4daf9eb22..aaafa0398fd5e7c24fafc9aab37a419bc6f92c9f 100644 (file)
@@ -883,6 +883,17 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
 {
        struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
        enum pvr2_config cfg = dip->config;
+       char msg[80];
+       unsigned int mcnt;
+
+       /* Construct the unregistration message *before* we actually
+          perform the unregistration step.  By doing it this way we don't
+          have to worry about potentially touching deleted resources. */
+       mcnt = scnprintf(msg, sizeof(msg) - 1,
+                        "pvrusb2: unregistered device %s [%s]",
+                        video_device_node_name(&dip->devbase),
+                        pvr2_config_get_name(cfg));
+       msg[mcnt] = 0;
 
        pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
 
@@ -894,9 +905,7 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
           are gone. */
        video_unregister_device(&dip->devbase);
 
-       printk(KERN_INFO "pvrusb2: unregistered device %s [%s]\n",
-              video_device_node_name(&dip->devbase),
-              pvr2_config_get_name(cfg));
+       printk(KERN_INFO "%s\n", msg);
 
 }
 
index 7fe70e7186565deb9155f592d30eae7284603771..fb242f6cfb1f23b313df0ae80510ef8ec6042539 100644 (file)
@@ -1247,7 +1247,7 @@ static bool pxa_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
                 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
 }
 
-static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
+static int pxa_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
                                  struct soc_camera_format_xlate *xlate)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
@@ -1264,7 +1264,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
 
        fmt = soc_mbus_get_fmtdesc(code);
        if (!fmt) {
-               dev_err(dev, "Invalid format code #%d: %d\n", idx, code);
+               dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
                return 0;
        }
 
index bbd9c11e2c5a721436230f6656f83806058ade54..47fd207ba3b1f63dd3edf9458ff0a7b98fa5f3b7 100644 (file)
@@ -481,10 +481,10 @@ static int reg_write_multiple(struct i2c_client *client,
        return 0;
 }
 
-static int rj54n1_enum_fmt(struct v4l2_subdev *sd, int index,
+static int rj54n1_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                           enum v4l2_mbus_pixelcode *code)
 {
-       if ((unsigned int)index >= ARRAY_SIZE(rj54n1_colour_fmts))
+       if (index >= ARRAY_SIZE(rj54n1_colour_fmts))
                return -EINVAL;
 
        *code = rj54n1_colour_fmts[index].code;
@@ -1444,7 +1444,6 @@ static int rj54n1_probe(struct i2c_client *client,
        ret = rj54n1_video_probe(icd, client, rj54n1_priv);
        if (ret < 0) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(rj54n1);
                return ret;
        }
@@ -1461,7 +1460,6 @@ static int rj54n1_remove(struct i2c_client *client)
        icd->ops = NULL;
        if (icl->free_bus)
                icl->free_bus(icl);
-       i2c_set_clientdata(client, NULL);
        client->driver = NULL;
        kfree(rj54n1);
 
index 53b6fcde3800076cd416ebc0eca82eb984834c88..76da74368680f9a10f747fc0c8322a56f2c630bd 100644 (file)
@@ -1117,13 +1117,6 @@ static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
        return 0;
 }
 
-static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
-       if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
-               return -EINVAL;
-       return saa711x_g_sliced_fmt(sd, &fmt->fmt.sliced);
-}
-
 static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
 {
        saa711x_set_lcr(sd, NULL);
@@ -1136,12 +1129,13 @@ static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
        return 0;
 }
 
-static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
 {
-       if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (fmt->code != V4L2_MBUS_FMT_FIXED)
                return -EINVAL;
-
-       return saa711x_set_size(sd, fmt->fmt.pix.width, fmt->fmt.pix.height);
+       fmt->field = V4L2_FIELD_INTERLACED;
+       fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+       return saa711x_set_size(sd, fmt->width, fmt->height);
 }
 
 /* Decode the sliced VBI data stream as created by the saa7115.
@@ -1556,8 +1550,7 @@ static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
 static const struct v4l2_subdev_video_ops saa711x_video_ops = {
        .s_routing = saa711x_s_routing,
        .s_crystal_freq = saa711x_s_crystal_freq,
-       .g_fmt = saa711x_g_fmt,
-       .s_fmt = saa711x_s_fmt,
+       .s_mbus_fmt = saa711x_s_mbus_fmt,
        .s_stream = saa711x_s_stream,
        .querystd = saa711x_querystd,
        .g_input_status = saa711x_g_input_status,
index 87986ad62f8698b5bee3a49094458ace5aff09f3..79fffcf39ba8562e25db013dbbb715f5cd4bd046 100644 (file)
@@ -645,13 +645,6 @@ static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
        return 0;
 }
 
-static int saa7127_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
-       if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
-               return -EINVAL;
-       return saa7127_g_sliced_fmt(sd, &fmt->fmt.sliced);
-}
-
 static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
 {
        switch (data->id) {
@@ -731,7 +724,6 @@ static const struct v4l2_subdev_core_ops saa7127_core_ops = {
 };
 
 static const struct v4l2_subdev_video_ops saa7127_video_ops = {
-       .g_fmt = saa7127_g_fmt,
        .s_std_output = saa7127_s_std_output,
        .s_routing = saa7127_s_routing,
        .s_stream = saa7127_s_stream,
index 1eabff6b2456a5744fcaf6b7fe0e42d344fab576..40fd31ca7716da6ae74ee2b76697fa4d615f54b0 100644 (file)
@@ -846,24 +846,28 @@ static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_control
        return 0;
 }
 
-static int saa6752hs_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
 {
        struct saa6752hs_state *h = to_state(sd);
 
        if (h->video_format == SAA6752HS_VF_UNKNOWN)
                h->video_format = SAA6752HS_VF_D1;
-       f->fmt.pix.width =
-               v4l2_format_table[h->video_format].fmt.pix.width;
-       f->fmt.pix.height =
-               v4l2_format_table[h->video_format].fmt.pix.height;
+       f->width = v4l2_format_table[h->video_format].fmt.pix.width;
+       f->height = v4l2_format_table[h->video_format].fmt.pix.height;
+       f->code = V4L2_MBUS_FMT_FIXED;
+       f->field = V4L2_FIELD_INTERLACED;
+       f->colorspace = V4L2_COLORSPACE_SMPTE170M;
        return 0;
 }
 
-static int saa6752hs_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
 {
        struct saa6752hs_state *h = to_state(sd);
        int dist_352, dist_480, dist_720;
 
+       if (f->code != V4L2_MBUS_FMT_FIXED)
+               return -EINVAL;
+
        /*
          FIXME: translate and round width/height into EMPRESS
          subsample type:
@@ -876,28 +880,30 @@ static int saa6752hs_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
          D1     | 720x576 | 720x480
        */
 
-       dist_352 = abs(f->fmt.pix.width - 352);
-       dist_480 = abs(f->fmt.pix.width - 480);
-       dist_720 = abs(f->fmt.pix.width - 720);
+       dist_352 = abs(f->width - 352);
+       dist_480 = abs(f->width - 480);
+       dist_720 = abs(f->width - 720);
        if (dist_720 < dist_480) {
-               f->fmt.pix.width = 720;
-               f->fmt.pix.height = 576;
+               f->width = 720;
+               f->height = 576;
                h->video_format = SAA6752HS_VF_D1;
        } else if (dist_480 < dist_352) {
-               f->fmt.pix.width = 480;
-               f->fmt.pix.height = 576;
+               f->width = 480;
+               f->height = 576;
                h->video_format = SAA6752HS_VF_2_3_D1;
        } else {
-               f->fmt.pix.width = 352;
-               if (abs(f->fmt.pix.height - 576) <
-                   abs(f->fmt.pix.height - 288)) {
-                       f->fmt.pix.height = 576;
+               f->width = 352;
+               if (abs(f->height - 576) <
+                   abs(f->height - 288)) {
+                       f->height = 576;
                        h->video_format = SAA6752HS_VF_1_2_D1;
                } else {
-                       f->fmt.pix.height = 288;
+                       f->height = 288;
                        h->video_format = SAA6752HS_VF_SIF;
                }
        }
+       f->field = V4L2_FIELD_INTERLACED;
+       f->colorspace = V4L2_COLORSPACE_SMPTE170M;
        return 0;
 }
 
@@ -932,8 +938,8 @@ static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
 };
 
 static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
-       .s_fmt = saa6752hs_s_fmt,
-       .g_fmt = saa6752hs_g_fmt,
+       .s_mbus_fmt = saa6752hs_s_mbus_fmt,
+       .g_mbus_fmt = saa6752hs_g_mbus_fmt,
 };
 
 static const struct v4l2_subdev_ops saa6752hs_ops = {
index 72700d4e394121fe6305588bbdff947ed4d1f695..07f6bb8ef9d949b36e52530d17a8350cf86648b9 100644 (file)
@@ -3897,6 +3897,40 @@ struct saa7134_board saa7134_boards[] = {
                        .gpio = 0x01,
                },
        },
+       [SAA7134_BOARD_AVERMEDIA_M733A] = {
+               .name           = "Avermedia PCI M733A",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 0,
+               .gpiomask       = 0x020200000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x00200000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x01,
+               },
+       },
        [SAA7134_BOARD_BEHOLD_401] = {
                /*       Beholder Intl. Ltd. 2008      */
                /*Dmitry Belimov <d.belimov@gmail.com> */
@@ -5820,6 +5854,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x1461, /* Avermedia Technologies Inc */
                .subdevice    = 0xf11d,
                .driver_data  = SAA7134_BOARD_AVERMEDIA_M135A,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0x4155,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_M733A,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0x4255,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_M733A,
        }, {
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
@@ -6786,6 +6832,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev,
        switch (dev->board) {
        case SAA7134_BOARD_HAUPPAUGE_HVR1150:
        case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+       case SAA7134_BOARD_AVERMEDIA_M733A:
                /* tda8290 + tda18271 */
                ret = saa7134_tda8290_18271_callback(dev, command, arg);
                break;
@@ -7087,6 +7134,14 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x0000C000, 0x0000C000);
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000C000, 0x0000C000);
                break;
+       case SAA7134_BOARD_AVERMEDIA_M733A:
+               saa7134_set_gpio(dev, 1, 1);
+               msleep(10);
+               saa7134_set_gpio(dev, 1, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 1, 1);
+               dev->has_remote = SAA7134_REMOTE_GPIO;
+               break;
        }
        return 0;
 }
index ea877a50f52d9b65963e1edfcf81b81f356b807e..e763f9fd0133f06c1ebed3f4add1ac82dc30f166 100644 (file)
@@ -223,9 +223,11 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
        struct saa7134_dev *dev = file->private_data;
+       struct v4l2_mbus_framefmt mbus_fmt;
 
-       saa_call_all(dev, video, g_fmt, f);
+       saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
 
+       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
 
@@ -236,8 +238,11 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
        struct saa7134_dev *dev = file->private_data;
+       struct v4l2_mbus_framefmt mbus_fmt;
 
-       saa_call_all(dev, video, s_fmt, f);
+       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+       saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
 
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
index e5565e2fd4262e4f92d7916f1d4eb4d9a1e6945e..0b336ca6d55b9a281c3e346193389587a2534852 100644 (file)
@@ -141,8 +141,8 @@ static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        struct saa7134_dev *dev = ir->c->adapter->algo_data;
 
        if (dev == NULL) {
-               dprintk("get_key_flydvb_trio: "
-                        "gir->c->adapter->algo_data is NULL!\n");
+               i2cdprintk("get_key_flydvb_trio: "
+                          "ir->c->adapter->algo_data is NULL!\n");
                return -EIO;
        }
 
@@ -195,8 +195,8 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
        /* <dev> is needed to access GPIO. Used by the saa_readl macro. */
        struct saa7134_dev *dev = ir->c->adapter->algo_data;
        if (dev == NULL) {
-               dprintk("get_key_msi_tvanywhere_plus: "
-                       "gir->c->adapter->algo_data is NULL!\n");
+               i2cdprintk("get_key_msi_tvanywhere_plus: "
+                          "ir->c->adapter->algo_data is NULL!\n");
                return -EIO;
        }
 
@@ -657,12 +657,19 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
                break;
        case SAA7134_BOARD_AVERMEDIA_M135A:
-               ir_codes     = RC_MAP_AVERMEDIA_M135A_RM_JX;
+               ir_codes     = RC_MAP_AVERMEDIA_M135A;
                mask_keydown = 0x0040000;       /* Enable GPIO18 line on both edges */
                mask_keyup   = 0x0040000;
                mask_keycode = 0xffff;
                raw_decode   = 1;
                break;
+       case SAA7134_BOARD_AVERMEDIA_M733A:
+               ir_codes     = RC_MAP_AVERMEDIA_M733A_RM_K6;
+               mask_keydown = 0x0040000;
+               mask_keyup   = 0x0040000;
+               mask_keycode = 0xffff;
+               raw_decode   = 1;
+               break;
        case SAA7134_BOARD_AVERMEDIA_777:
        case SAA7134_BOARD_AVERMEDIA_A16AR:
                ir_codes     = RC_MAP_AVERMEDIA;
@@ -815,7 +822,6 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                mask_keyup   = 0x020000;
                polling      = 50; /* ms */
                break;
-       break;
        }
        if (NULL == ir_codes) {
                printk("%s: Oops: IR config error [card=%d]\n",
index 3962534267be2b5af3259d9b983fe279710c436d..756a1ca8833d89a50153a910064d8ec8e0272fd9 100644 (file)
@@ -303,6 +303,7 @@ struct saa7134_format {
 #define SAA7134_BOARD_HAWELL_HW_404M7          177
 #define SAA7134_BOARD_BEHOLD_H7             178
 #define SAA7134_BOARD_BEHOLD_A7             179
+#define SAA7134_BOARD_AVERMEDIA_M733A       180
 
 #define SAA7134_MAXBOARDS 32
 #define SAA7134_INPUT_MAX 8
index d521c648e15706fa29e2d26dd012330519aaedff..78d69950c00abe1bc4ee70bd000e1ed2c3e051a3 100644 (file)
@@ -1199,28 +1199,32 @@ static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
 }
 #endif
 
-static int saa717x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int saa717x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
 {
-       struct v4l2_pix_format *pix;
        int prescale, h_scale, v_scale;
 
-       pix = &fmt->fmt.pix;
        v4l2_dbg(1, debug, sd, "decoder set size\n");
 
+       if (fmt->code != V4L2_MBUS_FMT_FIXED)
+               return -EINVAL;
+
        /* FIXME need better bounds checking here */
-       if (pix->width < 1 || pix->width > 1440)
+       if (fmt->width < 1 || fmt->width > 1440)
                return -EINVAL;
-       if (pix->height < 1 || pix->height > 960)
+       if (fmt->height < 1 || fmt->height > 960)
                return -EINVAL;
 
+       fmt->field = V4L2_FIELD_INTERLACED;
+       fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
        /* scaling setting */
        /* NTSC and interlace only */
-       prescale = SAA717X_NTSC_WIDTH / pix->width;
+       prescale = SAA717X_NTSC_WIDTH / fmt->width;
        if (prescale == 0)
                prescale = 1;
-       h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width;
+       h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / fmt->width;
        /* interlace */
-       v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height;
+       v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height;
 
        /* Horizontal prescaling etc */
        set_h_prescale(sd, 0, prescale);
@@ -1241,19 +1245,19 @@ static int saa717x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
        /* set video output size */
        /* video number of pixels at output */
        /* TASK A */
-       saa717x_write(sd, 0x5C, (u8)(pix->width & 0xFF));
-       saa717x_write(sd, 0x5D, (u8)((pix->width >> 8) & 0xFF));
+       saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF));
+       saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF));
        /* TASK B */
-       saa717x_write(sd, 0x9C, (u8)(pix->width & 0xFF));
-       saa717x_write(sd, 0x9D, (u8)((pix->width >> 8) & 0xFF));
+       saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF));
+       saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF));
 
        /* video number of lines at output */
        /* TASK A */
-       saa717x_write(sd, 0x5E, (u8)(pix->height & 0xFF));
-       saa717x_write(sd, 0x5F, (u8)((pix->height >> 8) & 0xFF));
+       saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF));
+       saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF));
        /* TASK B */
-       saa717x_write(sd, 0x9E, (u8)(pix->height & 0xFF));
-       saa717x_write(sd, 0x9F, (u8)((pix->height >> 8) & 0xFF));
+       saa717x_write(sd, 0x9E, (u8)(fmt->height & 0xFF));
+       saa717x_write(sd, 0x9F, (u8)((fmt->height >> 8) & 0xFF));
        return 0;
 }
 
@@ -1403,7 +1407,7 @@ static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = {
 
 static const struct v4l2_subdev_video_ops saa717x_video_ops = {
        .s_routing = saa717x_s_video_routing,
-       .s_fmt = saa717x_s_fmt,
+       .s_mbus_fmt = saa717x_s_mbus_fmt,
        .s_stream = saa717x_s_stream,
 };
 
index 4ac3b482fbb49cd206b8ec4c2db3017535525411..961bfa2fea97eb9f65a5900d36fcc0d181e2ffa2 100644 (file)
@@ -878,7 +878,7 @@ static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt)
 
 static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect);
 
-static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
+static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int idx,
                                     struct soc_camera_format_xlate *xlate)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
@@ -897,7 +897,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
        fmt = soc_mbus_get_fmtdesc(code);
        if (!fmt) {
                dev_err(icd->dev.parent,
-                       "Invalid format code #%d: %d\n", idx, code);
+                       "Invalid format code #%u: %d\n", idx, code);
                return -EINVAL;
        }
 
index 522ba3f4c285d8fbf8cc05b04d624a25fc61774e..b6643ca7656ae026b3d7d2fd62cbfc2970fdd8ee 100644 (file)
@@ -62,8 +62,8 @@ static const struct usb_device_id sn9c102_id_table[] = {
 #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
        { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
 /*     { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
-#endif
        { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
+#endif
        { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), },
        /* SN9C103 */
        { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), },
index db1ca0e90d7611e80905339d7730c2dc00668b86..475757bfd7ba5bbd0cff11ecf8ab4f963d5174f9 100644 (file)
@@ -200,7 +200,8 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-       int i, fmts = 0, raw_fmts = 0, ret;
+       unsigned int i, fmts = 0, raw_fmts = 0;
+       int ret;
        enum v4l2_mbus_pixelcode code;
 
        while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, raw_fmts, &code))
index 10b003a8be83c21fbf7b7964c6dc142c8c0e93f3..248c986f0989744bce6497d699fe4d43d038b850 100644 (file)
@@ -71,7 +71,7 @@ static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_core_ops platform_subdev_core_ops;
 
-static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, int index,
+static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                                        enum v4l2_mbus_pixelcode *code)
 {
        struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
index b90e9da3167dde4e38df0037832375e9aaa48e3f..54681a5358222df6a722451e92d9fd9e627d22f8 100644 (file)
@@ -850,7 +850,6 @@ static int tcm825x_probe(struct i2c_client *client,
                         const struct i2c_device_id *did)
 {
        struct tcm825x_sensor *sensor = &tcm825x;
-       int rval;
 
        if (i2c_get_clientdata(client))
                return -EBUSY;
@@ -871,11 +870,7 @@ static int tcm825x_probe(struct i2c_client *client,
        sensor->pix.height = tcm825x_sizes[QVGA].height;
        sensor->pix.pixelformat = V4L2_PIX_FMT_RGB565;
 
-       rval = v4l2_int_device_register(sensor->v4l2_int_device);
-       if (rval)
-               i2c_set_clientdata(client, NULL);
-
-       return rval;
+       return v4l2_int_device_register(sensor->v4l2_int_device);
 }
 
 static int tcm825x_remove(struct i2c_client *client)
@@ -886,7 +881,6 @@ static int tcm825x_remove(struct i2c_client *client)
                return -ENODEV; /* our client isn't attached */
 
        v4l2_int_device_unregister(sensor->v4l2_int_device);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index e826114b7fb887d7408c8f61202dc1ff6b928c69..71c73fa0d68c7d2b26a345c96bc1e299ea112a15 100644 (file)
@@ -88,9 +88,6 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable);
  * @pdata: Board specific
  * @ver: Chip version
  * @streaming: TVP5146/47 decoder streaming - enabled or disabled.
- * @pix: Current pixel format
- * @num_fmts: Number of formats
- * @fmt_list: Format list
  * @current_std: Current standard
  * @num_stds: Number of standards
  * @std_list: Standards list
@@ -105,13 +102,9 @@ struct tvp514x_decoder {
        int ver;
        int streaming;
 
-       struct v4l2_pix_format pix;
-       int num_fmts;
-       const struct v4l2_fmtdesc *fmt_list;
-
        enum tvp514x_std current_std;
        int num_stds;
-       struct tvp514x_std_info *std_list;
+       const struct tvp514x_std_info *std_list;
        /* Input and Output Routing parameters */
        u32 input;
        u32 output;
@@ -202,28 +195,13 @@ static struct tvp514x_reg tvp514x_reg_list_default[] = {
        {TOK_TERM, 0, 0},
 };
 
-/**
- * List of image formats supported by TVP5146/47 decoder
- * Currently we are using 8 bit mode only, but can be
- * extended to 10/20 bit mode.
- */
-static const struct v4l2_fmtdesc tvp514x_fmt_list[] = {
-       {
-        .index = 0,
-        .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
-        .flags = 0,
-        .description = "8-bit UYVY 4:2:2 Format",
-        .pixelformat = V4L2_PIX_FMT_UYVY,
-       },
-};
-
 /**
  * Supported standards -
  *
  * Currently supports two standards only, need to add support for rest of the
  * modes, like SECAM, etc...
  */
-static struct tvp514x_std_info tvp514x_std_list[] = {
+static const struct tvp514x_std_info tvp514x_std_list[] = {
        /* Standard: STD_NTSC_MJ */
        [STD_NTSC_MJ] = {
         .width = NTSC_NUM_ACTIVE_PIXELS,
@@ -366,13 +344,13 @@ static int tvp514x_write_regs(struct v4l2_subdev *sd,
 }
 
 /**
- * tvp514x_get_current_std() : Get the current standard detected by TVP5146/47
+ * tvp514x_query_current_std() : Query the current standard detected by TVP5146/47
  * @sd: ptr to v4l2_subdev struct
  *
- * Get current standard detected by TVP5146/47, STD_INVALID if there is no
+ * Returns the current standard detected by TVP5146/47, STD_INVALID if there is no
  * standard detected.
  */
-static enum tvp514x_std tvp514x_get_current_std(struct v4l2_subdev *sd)
+static enum tvp514x_std tvp514x_query_current_std(struct v4l2_subdev *sd)
 {
        u8 std, std_status;
 
@@ -518,7 +496,7 @@ static int tvp514x_detect(struct v4l2_subdev *sd,
  * @std_id: standard V4L2 std_id ioctl enum
  *
  * Returns the current standard detected by TVP5146/47. If no active input is
- * detected, returns -EINVAL
+ * detected then *std_id is set to 0 and the function returns 0.
  */
 static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
 {
@@ -530,10 +508,12 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
        if (std_id == NULL)
                return -EINVAL;
 
-       /* get the current standard */
-       current_std = tvp514x_get_current_std(sd);
+       *std_id = V4L2_STD_UNKNOWN;
+
+       /* query the current standard */
+       current_std = tvp514x_query_current_std(sd);
        if (current_std == STD_INVALID)
-               return -EINVAL;
+               return 0;
 
        input_sel = decoder->input;
 
@@ -575,12 +555,11 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
        /* check whether signal is locked */
        sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1);
        if (lock_mask != (sync_lock_status & lock_mask))
-               return -EINVAL; /* No input detected */
+               return 0;       /* No input detected */
 
-       decoder->current_std = current_std;
        *std_id = decoder->std_list[current_std].standard.id;
 
-       v4l2_dbg(1, debug, sd, "Current STD: %s",
+       v4l2_dbg(1, debug, sd, "Current STD: %s\n",
                        decoder->std_list[current_std].standard.name);
        return 0;
 }
@@ -614,7 +593,7 @@ static int tvp514x_s_std(struct v4l2_subdev *sd, v4l2_std_id std_id)
        decoder->tvp514x_regs[REG_VIDEO_STD].val =
                decoder->std_list[i].video_std;
 
-       v4l2_dbg(1, debug, sd, "Standard set to: %s",
+       v4l2_dbg(1, debug, sd, "Standard set to: %s\n",
                        decoder->std_list[i].standard.name);
        return 0;
 }
@@ -637,7 +616,6 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
        int err;
        enum tvp514x_input input_sel;
        enum tvp514x_output output_sel;
-       enum tvp514x_std current_std = STD_INVALID;
        u8 sync_lock_status, lock_mask;
        int try_count = LOCK_RETRY_COUNT;
 
@@ -721,11 +699,6 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
                /* Allow decoder to sync up with new input */
                msleep(LOCK_RETRY_DELAY);
 
-               /* get the current standard for future reference */
-               current_std = tvp514x_get_current_std(sd);
-               if (current_std == STD_INVALID)
-                       continue;
-
                sync_lock_status = tvp514x_read_reg(sd,
                                REG_STATUS1);
                if (lock_mask == (sync_lock_status & lock_mask))
@@ -733,15 +706,13 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
                        break;
        }
 
-       if ((current_std == STD_INVALID) || (try_count < 0))
+       if (try_count < 0)
                return -EINVAL;
 
-       decoder->current_std = current_std;
        decoder->input = input;
        decoder->output = output;
 
-       v4l2_dbg(1, debug, sd, "Input set to: %d, std : %d",
-                       input_sel, current_std);
+       v4l2_dbg(1, debug, sd, "Input set to: %d\n", input_sel);
 
        return 0;
 }
@@ -794,7 +765,7 @@ tvp514x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
                return err;
        }
 
-       v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d",
+       v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d\n",
                        qctrl->name, qctrl->minimum, qctrl->maximum,
                        qctrl->default_value);
 
@@ -851,7 +822,7 @@ tvp514x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
                return -EINVAL;
        }
 
-       v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d",
+       v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d\n",
                        ctrl->id, ctrl->value);
        return 0;
 }
@@ -951,7 +922,7 @@ tvp514x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
                return err;
        }
 
-       v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d",
+       v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d\n",
                        ctrl->id, ctrl->value);
 
        return err;
@@ -967,44 +938,33 @@ tvp514x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 static int
 tvp514x_enum_fmt_cap(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
 {
-       struct tvp514x_decoder *decoder = to_decoder(sd);
-       int index;
-
-       if (fmt == NULL)
-               return -EINVAL;
-
-       index = fmt->index;
-       if ((index >= decoder->num_fmts) || (index < 0))
-               /* Index out of bound */
+       if (fmt == NULL || fmt->index)
                return -EINVAL;
 
        if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                /* only capture is supported */
                return -EINVAL;
 
-       memcpy(fmt, &decoder->fmt_list[index],
-               sizeof(struct v4l2_fmtdesc));
-
-       v4l2_dbg(1, debug, sd, "Current FMT: index - %d (%s)",
-                       decoder->fmt_list[index].index,
-                       decoder->fmt_list[index].description);
+       /* only one format */
+       fmt->flags = 0;
+       strlcpy(fmt->description, "8-bit UYVY 4:2:2 Format",
+                                       sizeof(fmt->description));
+       fmt->pixelformat = V4L2_PIX_FMT_UYVY;
        return 0;
 }
 
 /**
- * tvp514x_try_fmt_cap() - V4L2 decoder interface handler for try_fmt
+ * tvp514x_fmt_cap() - V4L2 decoder interface handler for try/s/g_fmt
  * @sd: pointer to standard V4L2 sub-device structure
  * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure
  *
- * Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This
- * ioctl is used to negotiate the image capture size and pixel format
- * without actually making it take effect.
+ * Implement the VIDIOC_TRY/S/G_FMT ioctl for the CAPTURE buffer type. This
+ * ioctl is used to negotiate the image capture size and pixel format.
  */
 static int
-tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
+tvp514x_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
 {
        struct tvp514x_decoder *decoder = to_decoder(sd);
-       int ifmt;
        struct v4l2_pix_format *pix;
        enum tvp514x_std current_std;
 
@@ -1012,105 +972,29 @@ tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
                return -EINVAL;
 
        if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               /* only capture is supported */
-               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               return -EINVAL;
 
        pix = &f->fmt.pix;
 
        /* Calculate height and width based on current standard */
-       current_std = tvp514x_get_current_std(sd);
-       if (current_std == STD_INVALID)
-               return -EINVAL;
+       current_std = decoder->current_std;
 
-       decoder->current_std = current_std;
+       pix->pixelformat = V4L2_PIX_FMT_UYVY;
        pix->width = decoder->std_list[current_std].width;
        pix->height = decoder->std_list[current_std].height;
-
-       for (ifmt = 0; ifmt < decoder->num_fmts; ifmt++) {
-               if (pix->pixelformat ==
-                       decoder->fmt_list[ifmt].pixelformat)
-                       break;
-       }
-       if (ifmt == decoder->num_fmts)
-               /* None of the format matched, select default */
-               ifmt = 0;
-       pix->pixelformat = decoder->fmt_list[ifmt].pixelformat;
-
        pix->field = V4L2_FIELD_INTERLACED;
        pix->bytesperline = pix->width * 2;
        pix->sizeimage = pix->bytesperline * pix->height;
        pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
        pix->priv = 0;
 
-       v4l2_dbg(1, debug, sd, "Try FMT: pixelformat - %s, bytesperline - %d"
-                       "Width - %d, Height - %d",
-                       decoder->fmt_list[ifmt].description, pix->bytesperline,
+       v4l2_dbg(1, debug, sd, "FMT: bytesperline - %d"
+                       "Width - %d, Height - %d\n",
+                       pix->bytesperline,
                        pix->width, pix->height);
        return 0;
 }
 
-/**
- * tvp514x_s_fmt_cap() - V4L2 decoder interface handler for s_fmt
- * @sd: pointer to standard V4L2 sub-device structure
- * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure
- *
- * If the requested format is supported, configures the HW to use that
- * format, returns error code if format not supported or HW can't be
- * correctly configured.
- */
-static int
-tvp514x_s_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
-{
-       struct tvp514x_decoder *decoder = to_decoder(sd);
-       struct v4l2_pix_format *pix;
-       int rval;
-
-       if (f == NULL)
-               return -EINVAL;
-
-       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               /* only capture is supported */
-               return -EINVAL;
-
-       pix = &f->fmt.pix;
-       rval = tvp514x_try_fmt_cap(sd, f);
-       if (rval)
-               return rval;
-
-               decoder->pix = *pix;
-
-       return rval;
-}
-
-/**
- * tvp514x_g_fmt_cap() - V4L2 decoder interface handler for tvp514x_g_fmt_cap
- * @sd: pointer to standard V4L2 sub-device structure
- * @f: pointer to standard V4L2 v4l2_format structure
- *
- * Returns the decoder's current pixel format in the v4l2_format
- * parameter.
- */
-static int
-tvp514x_g_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
-{
-       struct tvp514x_decoder *decoder = to_decoder(sd);
-
-       if (f == NULL)
-               return -EINVAL;
-
-       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               /* only capture is supported */
-               return -EINVAL;
-
-       f->fmt.pix = decoder->pix;
-
-       v4l2_dbg(1, debug, sd, "Current FMT: bytesperline - %d"
-                       "Width - %d, Height - %d",
-                       decoder->pix.bytesperline,
-                       decoder->pix.width, decoder->pix.height);
-       return 0;
-}
-
 /**
  * tvp514x_g_parm() - V4L2 decoder interface handler for g_parm
  * @sd: pointer to standard V4L2 sub-device structure
@@ -1132,15 +1016,8 @@ tvp514x_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
                /* only capture is supported */
                return -EINVAL;
 
-       memset(a, 0, sizeof(*a));
-       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
        /* get the current standard */
-       current_std = tvp514x_get_current_std(sd);
-       if (current_std == STD_INVALID)
-               return -EINVAL;
-
-       decoder->current_std = current_std;
+       current_std = decoder->current_std;
 
        cparm = &a->parm.capture;
        cparm->capability = V4L2_CAP_TIMEPERFRAME;
@@ -1175,11 +1052,7 @@ tvp514x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
        timeperframe = &a->parm.capture.timeperframe;
 
        /* get the current standard */
-       current_std = tvp514x_get_current_std(sd);
-       if (current_std == STD_INVALID)
-               return -EINVAL;
-
-       decoder->current_std = current_std;
+       current_std = decoder->current_std;
 
        *timeperframe =
            decoder->std_list[current_std].standard.frameperiod;
@@ -1259,9 +1132,9 @@ static const struct v4l2_subdev_video_ops tvp514x_video_ops = {
        .s_routing = tvp514x_s_routing,
        .querystd = tvp514x_querystd,
        .enum_fmt = tvp514x_enum_fmt_cap,
-       .g_fmt = tvp514x_g_fmt_cap,
-       .try_fmt = tvp514x_try_fmt_cap,
-       .s_fmt = tvp514x_s_fmt_cap,
+       .g_fmt = tvp514x_fmt_cap,
+       .try_fmt = tvp514x_fmt_cap,
+       .s_fmt = tvp514x_fmt_cap,
        .g_parm = tvp514x_g_parm,
        .s_parm = tvp514x_s_parm,
        .s_stream = tvp514x_s_stream,
@@ -1274,22 +1147,6 @@ static const struct v4l2_subdev_ops tvp514x_ops = {
 
 static struct tvp514x_decoder tvp514x_dev = {
        .streaming = 0,
-
-       .fmt_list = tvp514x_fmt_list,
-       .num_fmts = ARRAY_SIZE(tvp514x_fmt_list),
-
-       .pix = {
-               /* Default to NTSC 8-bit YUV 422 */
-               .width = NTSC_NUM_ACTIVE_PIXELS,
-               .height = NTSC_NUM_ACTIVE_LINES,
-               .pixelformat = V4L2_PIX_FMT_UYVY,
-               .field = V4L2_FIELD_INTERLACED,
-               .bytesperline = NTSC_NUM_ACTIVE_PIXELS * 2,
-               .sizeimage =
-               NTSC_NUM_ACTIVE_PIXELS * 2 * NTSC_NUM_ACTIVE_LINES,
-               .colorspace = V4L2_COLORSPACE_SMPTE170M,
-               },
-
        .current_std = STD_NTSC_MJ,
        .std_list = tvp514x_std_list,
        .num_stds = ARRAY_SIZE(tvp514x_std_list),
index 47f0582d50a58e36ffb51d394f4b366fe92c776a..1654f65cca7c0dfe7c487b12fe32c37711a0b6e3 100644 (file)
@@ -934,17 +934,6 @@ static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
        return 0;
 }
 
-static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
-       switch (fmt->type) {
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-               return tvp5150_s_sliced_fmt(sd, &fmt->fmt.sliced);
-
-       default:
-               return -EINVAL;
-       }
-}
-
 static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
 {
        int i, mask = 0;
@@ -960,13 +949,6 @@ static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
        return 0;
 }
 
-static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
-       if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
-               return -EINVAL;
-       return tvp5150_g_sliced_fmt(sd, &fmt->fmt.sliced);
-}
-
 static int tvp5150_g_chip_ident(struct v4l2_subdev *sd,
                                struct v4l2_dbg_chip_ident *chip)
 {
@@ -1054,8 +1036,6 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
 
 static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
        .s_routing = tvp5150_s_routing,
-       .g_fmt = tvp5150_g_fmt,
-       .s_fmt = tvp5150_s_fmt,
 };
 
 static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
index 76be733eabfd4d3f7b4bc474219a6f0a9c8fb5ea..445dc93413e3ae32ffd7ab3654b3687b3ba600ce 100644 (file)
@@ -903,7 +903,7 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
 #endif
 };
 
-static int tw9910_enum_fmt(struct v4l2_subdev *sd, int index,
+static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                           enum v4l2_mbus_pixelcode *code)
 {
        if (index)
@@ -977,7 +977,6 @@ static int tw9910_probe(struct i2c_client *client,
        ret = tw9910_video_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(priv);
        }
 
@@ -990,7 +989,6 @@ static int tw9910_remove(struct i2c_client *client)
        struct soc_camera_device *icd = client->dev.platform_data;
 
        icd->ops = NULL;
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
        return 0;
 }
index 6248a639ba2d2ab6e097f5770a5f2b69fec643b1..c2690df33438bd65190157dc88c20e4164ad2caa 100644 (file)
@@ -1671,8 +1671,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
        PDEBUG(DBG_PROBE, "");
 
        if (usbvision == NULL) {
-               dev_err(&usbvision->dev->dev,
-                       "%s: usb_get_intfdata() failed\n", __func__);
+               pr_err("%s: usb_get_intfdata() failed\n", __func__);
                return;
        }
 
index c933b64d1283645071301eb4571b45e7ede1909a..bc02e6b21608be1ee4a0fcf4e52e3e6e7f383982 100644 (file)
@@ -200,8 +200,6 @@ static int __devexit pm860x_remove(struct i2c_client *client)
 
        pm860x_device_exit(chip);
        i2c_unregister_device(chip->companion);
-       i2c_set_clientdata(chip->client, NULL);
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return 0;
 }
index 53ebfee548fa3bfbc5311d34c98bfc5b166290b7..66379b413906a3ed5147370040ed7ccffd0b5068 100644 (file)
@@ -957,7 +957,6 @@ static int __init ab3100_probe(struct i2c_client *client,
        i2c_unregister_device(ab3100->testreg_client);
  exit_no_testreg_client:
  exit_no_detect:
-       i2c_set_clientdata(client, NULL);
        kfree(ab3100);
        return err;
 }
@@ -979,7 +978,6 @@ static int __exit ab3100_remove(struct i2c_client *client)
         * their notifiers so deactivate IRQ
         */
        free_irq(client->irq, ab3100);
-       i2c_set_clientdata(client, NULL);
        kfree(ab3100);
        return 0;
 }
index 1060f8e1c40a1cd0c280b2dbfcb3759fd932241e..f54ab62e7bc6b50a11558b470637889d8a5c6533 100644 (file)
@@ -1362,7 +1362,6 @@ static int __exit ab3550_remove(struct i2c_client *client)
         * their notifiers so deactivate IRQ
         */
        free_irq(client->irq, ab);
-       i2c_set_clientdata(client, NULL);
        kfree(ab);
        return 0;
 }
index 005532865654b0bbfa036bc873a37858220ffac1..3122139b430022d819b532ba90d4d7dbccf69c96 100644 (file)
@@ -302,7 +302,6 @@ out_free_irq:
                free_irq(chip->irq, chip);
 
 out_free_chip:
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
 
        return ret;
@@ -317,7 +316,6 @@ static int __devexit adp5520_remove(struct i2c_client *client)
 
        adp5520_remove_subdevs(chip);
        adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0);
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return 0;
 }
index 3ad915d0589c0626234ffdbc357afbbe2ff37af3..c07aece900fbb93b9ec08b2aa99ee85e144093fe 100644 (file)
@@ -534,7 +534,6 @@ static int __devinit da903x_probe(struct i2c_client *client,
 out_free_irq:
        free_irq(client->irq, chip);
 out_free_chip:
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return ret;
 }
@@ -544,7 +543,6 @@ static int __devexit da903x_remove(struct i2c_client *client)
        struct da903x_chip *chip = i2c_get_clientdata(client);
 
        da903x_remove_subdevs(chip);
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return 0;
 }
index e73f3f5252a89cf138dac35254263ed58630f72c..0219115e00c73f84c925045afceb96d65ea83ea3 100644 (file)
@@ -173,7 +173,6 @@ static int __devexit max8925_remove(struct i2c_client *client)
        max8925_device_exit(chip);
        i2c_unregister_device(chip->adc);
        i2c_unregister_device(chip->rtc);
-       i2c_set_clientdata(chip->i2c, NULL);
        kfree(chip);
        return 0;
 }
index 721948be12c77a7ad622e3559abc2f3953c1365a..a3fb4bcb98897718400da09d23dfd95116b99f58 100644 (file)
@@ -1228,7 +1228,6 @@ fail2:
        free_irq(client->irq, menelaus);
        flush_scheduled_work();
 fail1:
-       i2c_set_clientdata(client, NULL);
        kfree(menelaus);
        return err;
 }
@@ -1238,7 +1237,6 @@ static int __exit menelaus_remove(struct i2c_client *client)
        struct menelaus_chip    *menelaus = i2c_get_clientdata(client);
 
        free_irq(client->irq, menelaus);
-       i2c_set_clientdata(client, NULL);
        kfree(menelaus);
        the_menelaus = NULL;
        return 0;
index 704736e6e9b9b2efea2c66f4cf3a6ee36183eaa4..23e58552728596d7be431583e27602792b7e65d3 100644 (file)
@@ -336,7 +336,6 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
        return 0;
 
 err_free:
-       i2c_set_clientdata(client, NULL);
        kfree(pcf);
 
        return ret;
@@ -357,7 +356,6 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
        for (i = 0; i < PCF50633_NUM_REGULATORS; i++)
                platform_device_unregister(pcf->regulator_pdev[i]);
 
-       i2c_set_clientdata(client, NULL);
        kfree(pcf);
 
        return 0;
index 715f095dd7a6119b580e6eed2a6b425347ed88d4..e619e2a55997ebd0ed1ab6f27969da4497a78de9 100644 (file)
@@ -296,7 +296,6 @@ out_freeirq:
 out_removeirq:
        tc35892_irq_remove(tc35892);
 out_free:
-       i2c_set_clientdata(i2c, NULL);
        kfree(tc35892);
        return ret;
 }
@@ -310,7 +309,6 @@ static int __devexit tc35892_remove(struct i2c_client *client)
        free_irq(tc35892->i2c->irq, tc35892);
        tc35892_irq_remove(tc35892);
 
-       i2c_set_clientdata(client, NULL);
        kfree(tc35892);
 
        return 0;
index 9b22a77f70f5dac90aec0395d176d9ad06d4a71f..d0016b67d125ce40b8d9a810f1abb7ade2678756 100644 (file)
@@ -530,7 +530,6 @@ static int __exit tps65010_remove(struct i2c_client *client)
        cancel_delayed_work(&tps->work);
        flush_scheduled_work();
        debugfs_remove(tps->file);
-       i2c_set_clientdata(client, NULL);
        kfree(tps);
        the_tps = NULL;
        return 0;
index 7795af4b1fe15f7ee4690bd1a16eb17188ac492f..5fe5de166adb39bdafb2e7714ce046f58b6ccb3b 100644 (file)
@@ -80,7 +80,6 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
        return ret;
 
 err:
-       i2c_set_clientdata(i2c, NULL);
        kfree(wm8350);
        return ret;
 }
@@ -90,7 +89,6 @@ static int wm8350_i2c_remove(struct i2c_client *i2c)
        struct wm8350 *wm8350 = i2c_get_clientdata(i2c);
 
        wm8350_device_exit(wm8350);
-       i2c_set_clientdata(i2c, NULL);
        kfree(wm8350);
 
        return 0;
index e08aafa663dc4a1460bd901fd369fe9ec11a12b9..1bfef4846b07b0d98138c87509872937b2c29e6f 100644 (file)
@@ -415,7 +415,6 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
        return 0;
 
 struct_err:
-       i2c_set_clientdata(i2c, NULL);
        kfree(wm8400);
 err:
        return ret;
@@ -426,7 +425,6 @@ static int wm8400_i2c_remove(struct i2c_client *i2c)
        struct wm8400 *wm8400 = i2c_get_clientdata(i2c);
 
        wm8400_release(wm8400);
-       i2c_set_clientdata(i2c, NULL);
        kfree(wm8400);
 
        return 0;
index f7ca3a42b49089fcf48c6927260057d908641762..559b0b3c16c379584be01a08db209e2437549a04 100644 (file)
@@ -643,7 +643,6 @@ static int __devexit at24_remove(struct i2c_client *client)
 
        kfree(at24->writebuf);
        kfree(at24);
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index db9cd0240c6f3f84bc89c65b1e5b8750ce4db116..2a1e804a71aa2466199119f2206133fdb409d932 100644 (file)
@@ -45,7 +45,7 @@
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.2.1.0-K");
+MODULE_VERSION("1.2.1.1-k");
 MODULE_ALIAS("dmi:*:svnVMware*:*");
 MODULE_ALIAS("vmware_vmmemctl");
 MODULE_LICENSE("GPL");
@@ -101,6 +101,8 @@ MODULE_LICENSE("GPL");
 /* Maximum number of page allocations without yielding processor */
 #define VMW_BALLOON_YIELD_THRESHOLD    1024
 
+/* Maximum number of refused pages we accumulate during inflation cycle */
+#define VMW_BALLOON_MAX_REFUSED                16
 
 /*
  * Hypervisor communication port definitions.
@@ -183,6 +185,7 @@ struct vmballoon {
 
        /* transient list of non-balloonable pages */
        struct list_head refused_pages;
+       unsigned int n_refused_pages;
 
        /* balloon size in pages */
        unsigned int size;
@@ -428,14 +431,21 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
                /* inform monitor */
                locked = vmballoon_send_lock_page(b, page_to_pfn(page));
                if (!locked) {
+                       STATS_INC(b->stats.refused_alloc);
+
                        if (b->reset_required) {
                                __free_page(page);
                                return -EIO;
                        }
 
-                       /* place on list of non-balloonable pages, retry allocation */
+                       /*
+                        * Place page on the list of non-balloonable pages
+                        * and retry allocation, unless we already accumulated
+                        * too many of them, in which case take a breather.
+                        */
                        list_add(&page->lru, &b->refused_pages);
-                       STATS_INC(b->stats.refused_alloc);
+                       if (++b->n_refused_pages >= VMW_BALLOON_MAX_REFUSED)
+                               return -EIO;
                }
        } while (!locked);
 
@@ -483,6 +493,8 @@ static void vmballoon_release_refused_pages(struct vmballoon *b)
                __free_page(page);
                STATS_INC(b->stats.refused_free);
        }
+
+       b->n_refused_pages = 0;
 }
 
 /*
index e171e77f6129d8b80829099fabe0bdd1a8e25f71..f06d06e7fdfa06683d883f26397ace3d9f63970e 100644 (file)
@@ -249,7 +249,7 @@ config MMC_IMX
 
 config MMC_MSM7X00A
        tristate "Qualcomm MSM 7X00A SDCC Controller Support"
-       depends on MMC && ARCH_MSM
+       depends on MMC && ARCH_MSM && !ARCH_MSM7X30
        help
          This provides support for the SD/MMC cell found in the
           MSM 7X00A controllers from Qualcomm.
index 2b281680e3206da99f9e991d69f12c5edef92754..d98ddcfac5e5cb2e0ddf1fd32fac9318cc09b29b 100644 (file)
@@ -1157,7 +1157,6 @@ static void mmc_omap_start_request(struct mmc_omap_host *host,
        mmc_omap_start_command(host, req->cmd);
        if (host->dma_in_use)
                omap_start_dma(host->dma_ch);
-       BUG_ON(irqs_disabled());
 }
 
 static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
index eb97830c0344a57a7d458fc3430ab35165f6be76..5d3f824bb5a31078257ecbb0c10941fc874d3ad7 100644 (file)
 #define DRIVER_NAME    "sh_mmcif"
 #define DRIVER_VERSION "2010-04-28"
 
-#define MMCIF_CE_CMD_SET       0x00000000
-#define MMCIF_CE_ARG           0x00000008
-#define MMCIF_CE_ARG_CMD12     0x0000000C
-#define MMCIF_CE_CMD_CTRL      0x00000010
-#define MMCIF_CE_BLOCK_SET     0x00000014
-#define MMCIF_CE_CLK_CTRL      0x00000018
-#define MMCIF_CE_BUF_ACC       0x0000001C
-#define MMCIF_CE_RESP3         0x00000020
-#define MMCIF_CE_RESP2         0x00000024
-#define MMCIF_CE_RESP1         0x00000028
-#define MMCIF_CE_RESP0         0x0000002C
-#define MMCIF_CE_RESP_CMD12    0x00000030
-#define MMCIF_CE_DATA          0x00000034
-#define MMCIF_CE_INT           0x00000040
-#define MMCIF_CE_INT_MASK      0x00000044
-#define MMCIF_CE_HOST_STS1     0x00000048
-#define MMCIF_CE_HOST_STS2     0x0000004C
-#define MMCIF_CE_VERSION       0x0000007C
-
 /* CE_CMD_SET */
 #define CMD_MASK               0x3f000000
 #define CMD_SET_RTYP_NO                ((0 << 23) | (0 << 22))
@@ -207,27 +188,17 @@ struct sh_mmcif_host {
        wait_queue_head_t intr_wait;
 };
 
-static inline u32 sh_mmcif_readl(struct sh_mmcif_host *host, unsigned int reg)
-{
-       return readl(host->addr + reg);
-}
-
-static inline void sh_mmcif_writel(struct sh_mmcif_host *host,
-                                       unsigned int reg, u32 val)
-{
-       writel(val, host->addr + reg);
-}
 
 static inline void sh_mmcif_bitset(struct sh_mmcif_host *host,
                                        unsigned int reg, u32 val)
 {
-       writel(val | sh_mmcif_readl(host, reg), host->addr + reg);
+       writel(val | readl(host->addr + reg), host->addr + reg);
 }
 
 static inline void sh_mmcif_bitclr(struct sh_mmcif_host *host,
                                        unsigned int reg, u32 val)
 {
-       writel(~val & sh_mmcif_readl(host, reg), host->addr + reg);
+       writel(~val & readl(host->addr + reg), host->addr + reg);
 }
 
 
@@ -253,10 +224,10 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
 {
        u32 tmp;
 
-       tmp = 0x010f0000 & sh_mmcif_readl(host, MMCIF_CE_CLK_CTRL);
+       tmp = 0x010f0000 & sh_mmcif_readl(host->addr, MMCIF_CE_CLK_CTRL);
 
-       sh_mmcif_writel(host, MMCIF_CE_VERSION, SOFT_RST_ON);
-       sh_mmcif_writel(host, MMCIF_CE_VERSION, SOFT_RST_OFF);
+       sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_ON);
+       sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_OFF);
        sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp |
                SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29);
        /* byte swap on */
@@ -271,12 +242,10 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
        host->sd_error = 0;
        host->wait_int = 0;
 
-       state1 = sh_mmcif_readl(host, MMCIF_CE_HOST_STS1);
-       state2 = sh_mmcif_readl(host, MMCIF_CE_HOST_STS2);
-       pr_debug("%s: ERR HOST_STS1 = %08x\n", \
-                       DRIVER_NAME, sh_mmcif_readl(host, MMCIF_CE_HOST_STS1));
-       pr_debug("%s: ERR HOST_STS2 = %08x\n", \
-                       DRIVER_NAME, sh_mmcif_readl(host, MMCIF_CE_HOST_STS2));
+       state1 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1);
+       state2 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS2);
+       pr_debug("%s: ERR HOST_STS1 = %08x\n", DRIVER_NAME, state1);
+       pr_debug("%s: ERR HOST_STS2 = %08x\n", DRIVER_NAME, state2);
 
        if (state1 & STS1_CMDSEQ) {
                sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK);
@@ -288,7 +257,7 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
                                        "command sequence timeout err\n");
                                return -EIO;
                        }
-                       if (!(sh_mmcif_readl(host, MMCIF_CE_HOST_STS1)
+                       if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1)
                                                                & STS1_CMDSEQ))
                                break;
                        mdelay(1);
@@ -330,9 +299,9 @@ static int sh_mmcif_single_read(struct sh_mmcif_host *host,
 
        host->wait_int = 0;
        blocksize = (BLOCK_SIZE_MASK &
-                       sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET)) + 3;
+                       sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
        for (i = 0; i < blocksize / 4; i++)
-               *p++ = sh_mmcif_readl(host, MMCIF_CE_DATA);
+               *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);
 
        /* buffer read end */
        sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
@@ -353,7 +322,8 @@ static int sh_mmcif_multi_read(struct sh_mmcif_host *host,
        long time;
        u32 blocksize, i, j, sec, *p;
 
-       blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET);
+       blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
+                                                    MMCIF_CE_BLOCK_SET);
        for (j = 0; j < data->sg_len; j++) {
                p = sg_virt(data->sg);
                host->wait_int = 0;
@@ -370,7 +340,8 @@ static int sh_mmcif_multi_read(struct sh_mmcif_host *host,
 
                        host->wait_int = 0;
                        for (i = 0; i < blocksize / 4; i++)
-                               *p++ = sh_mmcif_readl(host, MMCIF_CE_DATA);
+                               *p++ = sh_mmcif_readl(host->addr,
+                                                     MMCIF_CE_DATA);
                }
                if (j < data->sg_len - 1)
                        data->sg++;
@@ -397,9 +368,9 @@ static int sh_mmcif_single_write(struct sh_mmcif_host *host,
 
        host->wait_int = 0;
        blocksize = (BLOCK_SIZE_MASK &
-                       sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET)) + 3;
+                       sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
        for (i = 0; i < blocksize / 4; i++)
-               sh_mmcif_writel(host, MMCIF_CE_DATA, *p++);
+               sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++);
 
        /* buffer write end */
        sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
@@ -421,7 +392,8 @@ static int sh_mmcif_multi_write(struct sh_mmcif_host *host,
        long time;
        u32 i, sec, j, blocksize, *p;
 
-       blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET);
+       blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
+                                                    MMCIF_CE_BLOCK_SET);
 
        for (j = 0; j < data->sg_len; j++) {
                p = sg_virt(data->sg);
@@ -439,7 +411,8 @@ static int sh_mmcif_multi_write(struct sh_mmcif_host *host,
 
                        host->wait_int = 0;
                        for (i = 0; i < blocksize / 4; i++)
-                               sh_mmcif_writel(host, MMCIF_CE_DATA, *p++);
+                               sh_mmcif_writel(host->addr,
+                                               MMCIF_CE_DATA, *p++);
                }
                if (j < data->sg_len - 1)
                        data->sg++;
@@ -451,18 +424,18 @@ static void sh_mmcif_get_response(struct sh_mmcif_host *host,
                                                struct mmc_command *cmd)
 {
        if (cmd->flags & MMC_RSP_136) {
-               cmd->resp[0] = sh_mmcif_readl(host, MMCIF_CE_RESP3);
-               cmd->resp[1] = sh_mmcif_readl(host, MMCIF_CE_RESP2);
-               cmd->resp[2] = sh_mmcif_readl(host, MMCIF_CE_RESP1);
-               cmd->resp[3] = sh_mmcif_readl(host, MMCIF_CE_RESP0);
+               cmd->resp[0] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP3);
+               cmd->resp[1] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP2);
+               cmd->resp[2] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP1);
+               cmd->resp[3] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP0);
        } else
-               cmd->resp[0] = sh_mmcif_readl(host, MMCIF_CE_RESP0);
+               cmd->resp[0] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP0);
 }
 
 static void sh_mmcif_get_cmd12response(struct sh_mmcif_host *host,
                                                struct mmc_command *cmd)
 {
-       cmd->resp[0] = sh_mmcif_readl(host, MMCIF_CE_RESP_CMD12);
+       cmd->resp[0] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP_CMD12);
 }
 
 static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
@@ -596,18 +569,19 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
                MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO;
 
        if (host->data) {
-               sh_mmcif_writel(host, MMCIF_CE_BLOCK_SET, 0);
-               sh_mmcif_writel(host, MMCIF_CE_BLOCK_SET, mrq->data->blksz);
+               sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0);
+               sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET,
+                               mrq->data->blksz);
        }
        opc = sh_mmcif_set_cmd(host, mrq, cmd, opc);
 
-       sh_mmcif_writel(host, MMCIF_CE_INT, 0xD80430C0);
-       sh_mmcif_writel(host, MMCIF_CE_INT_MASK, mask);
+       sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
+       sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
        /* set arg */
-       sh_mmcif_writel(host, MMCIF_CE_ARG, cmd->arg);
+       sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
        host->wait_int = 0;
        /* set cmd */
-       sh_mmcif_writel(host, MMCIF_CE_CMD_SET, opc);
+       sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc);
 
        time = wait_event_interruptible_timeout(host->intr_wait,
                host->wait_int == 1 || host->sd_error == 1, host->timeout);
@@ -752,43 +726,44 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
        u32 state = 0;
        int err = 0;
 
-       state = sh_mmcif_readl(host, MMCIF_CE_INT);
+       state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
 
        if (state & INT_RBSYE) {
-               sh_mmcif_writel(host, MMCIF_CE_INT, ~(INT_RBSYE | INT_CRSPE));
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT,
+                               ~(INT_RBSYE | INT_CRSPE));
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE);
        } else if (state & INT_CRSPE) {
-               sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_CRSPE);
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_CRSPE);
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCRSPE);
        } else if (state & INT_BUFREN) {
-               sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_BUFREN);
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFREN);
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
        } else if (state & INT_BUFWEN) {
-               sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_BUFWEN);
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFWEN);
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
        } else if (state & INT_CMD12DRE) {
-               sh_mmcif_writel(host, MMCIF_CE_INT,
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT,
                        ~(INT_CMD12DRE | INT_CMD12RBE |
                          INT_CMD12CRE | INT_BUFRE));
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE);
        } else if (state & INT_BUFRE) {
-               sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_BUFRE);
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFRE);
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
        } else if (state & INT_DTRANE) {
-               sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_DTRANE);
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_DTRANE);
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
        } else if (state & INT_CMD12RBE) {
-               sh_mmcif_writel(host, MMCIF_CE_INT,
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT,
                                ~(INT_CMD12RBE | INT_CMD12CRE));
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE);
        } else if (state & INT_ERR_STS) {
                /* err interrupts */
-               sh_mmcif_writel(host, MMCIF_CE_INT, ~state);
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
                err = 1;
        } else {
                pr_debug("%s: Not support int\n", DRIVER_NAME);
-               sh_mmcif_writel(host, MMCIF_CE_INT, ~state);
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
                err = 1;
        }
@@ -894,12 +869,12 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
                goto clean_up2;
        }
 
-       sh_mmcif_writel(host, MMCIF_CE_INT_MASK, MASK_ALL);
+       sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
        sh_mmcif_detect(host->mmc);
 
        pr_info("%s: driver version %s\n", DRIVER_NAME, DRIVER_VERSION);
        pr_debug("%s: chip ver H'%04x\n", DRIVER_NAME,
-                       sh_mmcif_readl(host, MMCIF_CE_VERSION) & 0x0000ffff);
+               sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
        return ret;
 
 clean_up2:
@@ -917,7 +892,7 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
        struct sh_mmcif_host *host = platform_get_drvdata(pdev);
        int irq[2];
 
-       sh_mmcif_writel(host, MMCIF_CE_INT_MASK, MASK_ALL);
+       sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 
        irq[0] = platform_get_irq(pdev, 0);
        irq[1] = platform_get_irq(pdev, 1);
index eb476b7f8d113cdadd87f558994a1fe95061cf49..f4ce273e93fd5e5888adbc73c9e684bd5568849c 100644 (file)
@@ -234,7 +234,6 @@ static int __devexit pismo_remove(struct i2c_client *client)
        /* FIXME: set_vpp needs saner arguments */
        pismo_setvpp_remove_fix(pismo);
 
-       i2c_set_clientdata(client, NULL);
        kfree(pismo);
 
        return 0;
@@ -286,7 +285,6 @@ static int __devinit pismo_probe(struct i2c_client *client,
        return 0;
 
  exit_free:
-       i2c_set_clientdata(client, NULL);
        kfree(pismo);
        return ret;
 }
index 000d65ea55a42bf495ba773dca6c66f99f0d3136..91c8013cf0d9b8b818d8587ef036e1229e7c3396 100644 (file)
@@ -404,14 +404,9 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
        if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
                return -EINVAL;
 
-       ops.oobbuf = kmalloc(length, GFP_KERNEL);
-       if (!ops.oobbuf)
-               return -ENOMEM;
-
-       if (copy_from_user(ops.oobbuf, ptr, length)) {
-               kfree(ops.oobbuf);
-               return -EFAULT;
-       }
+       ops.oobbuf = memdup_user(ptr, length);
+       if (IS_ERR(ops.oobbuf))
+               return PTR_ERR(ops.oobbuf);
 
        start &= ~((uint64_t)mtd->oobsize - 1);
        ret = mtd->write_oob(mtd, start, &ops);
index 98a04b3c9526e4bbd6a711b24846c98482fb01d6..ffc3720929f10efaca858758902e891220423ee3 100644 (file)
@@ -1,13 +1,3 @@
-menuconfig MTD_NAND
-       tristate "NAND Device Support"
-       depends on MTD
-       select MTD_NAND_IDS
-       select MTD_NAND_ECC
-       help
-         This enables support for accessing all type of NAND flash
-         devices. For further information see
-         <http://www.linux-mtd.infradead.org/doc/nand.html>.
-
 config MTD_NAND_ECC
        tristate
 
@@ -19,6 +9,17 @@ config MTD_NAND_ECC_SMC
          Software ECC according to the Smart Media Specification.
          The original Linux implementation had byte 0 and 1 swapped.
 
+
+menuconfig MTD_NAND
+       tristate "NAND Device Support"
+       depends on MTD
+       select MTD_NAND_IDS
+       select MTD_NAND_ECC
+       help
+         This enables support for accessing all type of NAND flash
+         devices. For further information see
+         <http://www.linux-mtd.infradead.org/doc/nand.html>.
+
 if MTD_NAND
 
 config MTD_NAND_VERIFY_WRITE
index 00aea6f7d1f1bc6bbf8bfae8080bce0b01c633e7..1312eda57ba6621c335fe592f7a7d963a5d05a5d 100644 (file)
@@ -232,7 +232,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
        if (!fun)
                return -ENOMEM;
 
-       ret = of_address_to_resource(ofdev->node, 0, &io_res);
+       ret = of_address_to_resource(ofdev->dev.of_node, 0, &io_res);
        if (ret) {
                dev_err(&ofdev->dev, "can't get IO base\n");
                goto err1;
@@ -244,7 +244,8 @@ static int __devinit fun_probe(struct of_device *ofdev,
                goto err1;
        }
 
-       prop = of_get_property(ofdev->node, "fsl,upm-addr-offset", &size);
+       prop = of_get_property(ofdev->dev.of_node, "fsl,upm-addr-offset",
+                              &size);
        if (!prop || size != sizeof(uint32_t)) {
                dev_err(&ofdev->dev, "can't get UPM address offset\n");
                ret = -EINVAL;
@@ -252,7 +253,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
        }
        fun->upm_addr_offset = *prop;
 
-       prop = of_get_property(ofdev->node, "fsl,upm-cmd-offset", &size);
+       prop = of_get_property(ofdev->dev.of_node, "fsl,upm-cmd-offset", &size);
        if (!prop || size != sizeof(uint32_t)) {
                dev_err(&ofdev->dev, "can't get UPM command offset\n");
                ret = -EINVAL;
@@ -260,7 +261,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
        }
        fun->upm_cmd_offset = *prop;
 
-       prop = of_get_property(ofdev->node,
+       prop = of_get_property(ofdev->dev.of_node,
                               "fsl,upm-addr-line-cs-offsets", &size);
        if (prop && (size / sizeof(uint32_t)) > 0) {
                fun->mchip_count = size / sizeof(uint32_t);
@@ -276,7 +277,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
 
        for (i = 0; i < fun->mchip_count; i++) {
                fun->rnb_gpio[i] = -1;
-               rnb_gpio = of_get_gpio(ofdev->node, i);
+               rnb_gpio = of_get_gpio(ofdev->dev.of_node, i);
                if (rnb_gpio >= 0) {
                        ret = gpio_request(rnb_gpio, dev_name(&ofdev->dev));
                        if (ret) {
@@ -292,13 +293,13 @@ static int __devinit fun_probe(struct of_device *ofdev,
                }
        }
 
-       prop = of_get_property(ofdev->node, "chip-delay", NULL);
+       prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL);
        if (prop)
                fun->chip_delay = *prop;
        else
                fun->chip_delay = 50;
 
-       prop = of_get_property(ofdev->node, "fsl,upm-wait-flags", &size);
+       prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size);
        if (prop && size == sizeof(uint32_t))
                fun->wait_flags = *prop;
        else
@@ -315,7 +316,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
        fun->dev = &ofdev->dev;
        fun->last_ctrl = NAND_CLE;
 
-       ret = fun_chip_init(fun, ofdev->node, &io_res);
+       ret = fun_chip_init(fun, ofdev->dev.of_node, &io_res);
        if (ret)
                goto err2;
 
index 3d0867d829cb01a02976328aa2fd1fe858b3fcf1..0a130dcaa1292974b264199824ec602fe002b677 100644 (file)
@@ -650,7 +650,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 static int __devinit mpc5121_nfc_probe(struct of_device *op,
                                        const struct of_device_id *match)
 {
-       struct device_node *rootnode, *dn = op->node;
+       struct device_node *rootnode, *dn = op->dev.of_node;
        struct device *dev = &op->dev;
        struct mpc5121_nfc_prv *prv;
        struct resource res;
@@ -889,12 +889,12 @@ static struct of_device_id mpc5121_nfc_match[] __devinitdata = {
 };
 
 static struct of_platform_driver mpc5121_nfc_driver = {
-       .match_table    = mpc5121_nfc_match,
        .probe          = mpc5121_nfc_probe,
        .remove         = __devexit_p(mpc5121_nfc_remove),
        .driver         = {
-               .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = mpc5121_nfc_match,
        },
 };
 
index 78a4232954748641e7fcd655056d83404b3d87a1..bcfc851fe55069bc93ffb38b28f8985a4b87f704 100644 (file)
@@ -150,7 +150,6 @@ static void r852_dma_done(struct r852_device *dev, int error)
        if (dev->phys_dma_addr && dev->phys_dma_addr != dev->phys_bounce_buffer)
                pci_unmap_single(dev->pci_dev, dev->phys_dma_addr, R852_DMA_LEN,
                        dev->dma_dir ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
-       complete(&dev->dma_done);
 }
 
 /*
@@ -182,6 +181,7 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read)
        /* Set dma direction */
        dev->dma_dir = do_read;
        dev->dma_stage = 1;
+       INIT_COMPLETION(dev->dma_done);
 
        dbg_verbose("doing dma %s ", do_read ? "read" : "write");
 
@@ -494,6 +494,11 @@ int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
        if (dev->card_unstable)
                return 0;
 
+       if (dev->dma_error) {
+               dev->dma_error = 0;
+               return -1;
+       }
+
        r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS);
        ecc_reg = r852_read_reg_dword(dev, R852_DATALINE);
        r852_write_reg(dev, R852_CTL, dev->ctlreg);
@@ -707,6 +712,7 @@ void r852_card_detect_work(struct work_struct *work)
                container_of(work, struct r852_device, card_detect_work.work);
 
        r852_card_update_present(dev);
+       r852_update_card_detect(dev);
        dev->card_unstable = 0;
 
        /* False alarm */
@@ -722,7 +728,6 @@ void r852_card_detect_work(struct work_struct *work)
        else
                r852_unregister_nand_device(dev);
 exit:
-       /* Update detection logic */
        r852_update_card_detect(dev);
 }
 
@@ -796,6 +801,7 @@ static irqreturn_t r852_irq(int irq, void *data)
                if (dma_status & R852_DMA_IRQ_ERROR) {
                        dbg("recieved dma error IRQ");
                        r852_dma_done(dev, -EIO);
+                       complete(&dev->dma_done);
                        goto out;
                }
 
@@ -825,8 +831,10 @@ static irqreturn_t r852_irq(int irq, void *data)
                        r852_dma_enable(dev);
 
                /* Operation done */
-               if (dev->dma_stage == 3)
+               if (dev->dma_stage == 3) {
                        r852_dma_done(dev, 0);
+                       complete(&dev->dma_done);
+               }
                goto out;
        }
 
@@ -940,18 +948,19 @@ int  r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 
        r852_dma_test(dev);
 
+       dev->irq = pci_dev->irq;
+       spin_lock_init(&dev->irqlock);
+
+       dev->card_detected = 0;
+       r852_card_update_present(dev);
+
        /*register irq handler*/
        error = -ENODEV;
        if (request_irq(pci_dev->irq, &r852_irq, IRQF_SHARED,
                          DRV_NAME, dev))
                goto error10;
 
-       dev->irq = pci_dev->irq;
-       spin_lock_init(&dev->irqlock);
-
        /* kick initial present test */
-       dev->card_detected = 0;
-       r852_card_update_present(dev);
        queue_delayed_work(dev->card_workqueue,
                &dev->card_detect_work, 0);
 
@@ -1081,7 +1090,7 @@ int r852_resume(struct device *device)
                        dev->card_detected ? "added" : "removed");
 
                queue_delayed_work(dev->card_workqueue,
-               &dev->card_detect_work, 1000);
+               &dev->card_detect_work, msecs_to_jiffies(1000));
                return 0;
        }
 
index 884852dc7eb44b29d1788fb43db7c3f6846c6936..cc728b12de82d4446315f91c165a032aa15f1c4b 100644 (file)
@@ -183,7 +183,7 @@ static int __devinit socrates_nand_probe(struct of_device *ofdev,
                return -ENOMEM;
        }
 
-       host->io_base = of_iomap(ofdev->node, 0);
+       host->io_base = of_iomap(ofdev->dev.of_node, 0);
        if (host->io_base == NULL) {
                printk(KERN_ERR "socrates_nand: ioremap failed\n");
                kfree(host);
@@ -244,7 +244,7 @@ static int __devinit socrates_nand_probe(struct of_device *ofdev,
 #ifdef CONFIG_MTD_OF_PARTS
        if (num_partitions == 0) {
                num_partitions = of_mtd_parse_partitions(&ofdev->dev,
-                                                        ofdev->node,
+                                                        ofdev->dev.of_node,
                                                         &partitions);
                if (num_partitions < 0) {
                        res = num_partitions;
index 9c149750e2bf9754518941e9233e94800d45b889..284a5f4a63ac8a48c955125c64e67ae8b89e16f9 100644 (file)
@@ -598,8 +598,8 @@ rx_next:
                        goto rx_status_loop;
 
                spin_lock_irqsave(&cp->lock, flags);
-               cpw16_f(IntrMask, cp_intr_mask);
                __napi_complete(napi);
+               cpw16_f(IntrMask, cp_intr_mask);
                spin_unlock_irqrestore(&cp->lock, flags);
        }
 
index 4ba72933f0da57b72f069e4d95a29fc1ad8da1f1..97d8068b372b228d6764055ad1d0529439c940af 100644 (file)
@@ -860,6 +860,7 @@ retry:
                }
 
        /* if unknown chip, assume array element #0, original RTL-8139 in this case */
+       i = 0;
        dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n");
        dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig));
        tp->chipset = 0;
@@ -2088,8 +2089,8 @@ static int rtl8139_poll(struct napi_struct *napi, int budget)
                 * again when we think we are done.
                 */
                spin_lock_irqsave(&tp->lock, flags);
-               RTL_W16_F(IntrMask, rtl8139_intr_mask);
                __napi_complete(napi);
+               RTL_W16_F(IntrMask, rtl8139_intr_mask);
                spin_unlock_irqrestore(&tp->lock, flags);
        }
        spin_unlock(&tp->rx_lock);
index 2decc597bda704bd74fac951551517421fc0a4e1..ce2fcdd4ab90521af8a8fb9a3f873b796b0a2bd9 100644 (file)
@@ -2754,6 +2754,7 @@ config MYRI10GE_DCA
 config NETXEN_NIC
        tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
        depends on PCI
+       select FW_LOADER
        help
          This enables the support for NetXen's Gigabit Ethernet card.
 
@@ -2819,6 +2820,7 @@ config BNX2X
 config QLCNIC
        tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"
        depends on PCI
+       select FW_LOADER
        help
          This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
          devices.
index 9d11dbf5e4da2d96d941a48c2af51d8bae9bdb57..b9ad799c719f1d5b541a33d93d095318e6c362fc 100644 (file)
@@ -1429,7 +1429,7 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        wrb = wrb_from_mccq(adapter);
        if (!wrb) {
                status = -EBUSY;
-               goto err;
+               goto err_unlock;
        }
        req = cmd->va;
        sge = nonembedded_sgl(wrb);
@@ -1457,7 +1457,10 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        else
                status = adapter->flash_status;
 
-err:
+       return status;
+
+err_unlock:
+       spin_unlock_bh(&adapter->mcc_lock);
        return status;
 }
 
@@ -1497,7 +1500,7 @@ err:
        return status;
 }
 
-extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
+int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
                                struct be_dma_mem *nonemb_cmd)
 {
        struct be_mcc_wrb *wrb;
@@ -1590,7 +1593,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
                        OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req));
-       req->hdr.timeout = 4;
+       req->hdr.timeout = cpu_to_le32(4);
 
        req->pattern = cpu_to_le64(pattern);
        req->src_port = cpu_to_le32(port_num);
@@ -1662,7 +1665,7 @@ err:
        return status;
 }
 
-extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
+int be_cmd_get_seeprom_data(struct be_adapter *adapter,
                                struct be_dma_mem *nonemb_cmd)
 {
        struct be_mcc_wrb *wrb;
index 39250b2ca886e9c7216ffcc956870c1320f85d0e..959add2410bf1787f8dff73ff786582be105831e 100644 (file)
@@ -1654,8 +1654,11 @@ MODULE_DEVICE_TABLE (of, bmac_match);
 
 static struct macio_driver bmac_driver =
 {
-       .name           = "bmac",
-       .match_table    = bmac_match,
+       .driver = {
+               .name           = "bmac",
+               .owner          = THIS_MODULE,
+               .of_match_table = bmac_match,
+       },
        .probe          = bmac_probe,
        .remove         = bmac_remove,
 #ifdef CONFIG_PM
index 188e356c30a30e005a69eaf05997ea57fdae880e..117432222a09e8b3c7521c6bf237621afe938fd9 100644 (file)
@@ -247,6 +247,7 @@ static const struct flash_spec flash_5709 = {
 MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
 
 static void bnx2_init_napi(struct bnx2 *bp);
+static void bnx2_del_napi(struct bnx2 *bp);
 
 static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
 {
@@ -3072,7 +3073,6 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
        u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
        struct l2_fhdr *rx_hdr;
        int rx_pkt = 0, pg_ring_used = 0;
-       struct pci_dev *pdev = bp->pdev;
 
        hw_cons = bnx2_get_hw_rx_cons(bnapi);
        sw_cons = rxr->rx_cons;
@@ -3098,12 +3098,10 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
                skb = rx_buf->skb;
                prefetchw(skb);
 
-               if (!get_dma_ops(&pdev->dev)->sync_single_for_cpu) {
-                       next_rx_buf =
-                               &rxr->rx_buf_ring[
-                                       RX_RING_IDX(NEXT_RX_BD(sw_cons))];
-                       prefetch(next_rx_buf->desc);
-               }
+               next_rx_buf =
+                       &rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))];
+               prefetch(next_rx_buf->desc);
+
                rx_buf->skb = NULL;
 
                dma_addr = dma_unmap_addr(rx_buf, mapping);
@@ -6270,6 +6268,7 @@ open_err:
        bnx2_free_skbs(bp);
        bnx2_free_irq(bp);
        bnx2_free_mem(bp);
+       bnx2_del_napi(bp);
        return rc;
 }
 
@@ -6537,6 +6536,7 @@ bnx2_close(struct net_device *dev)
        bnx2_free_irq(bp);
        bnx2_free_skbs(bp);
        bnx2_free_mem(bp);
+       bnx2_del_napi(bp);
        bp->link_up = 0;
        netif_carrier_off(bp->dev);
        bnx2_set_power_state(bp, PCI_D3hot);
@@ -8227,7 +8227,16 @@ bnx2_bus_string(struct bnx2 *bp, char *str)
        return str;
 }
 
-static void __devinit
+static void
+bnx2_del_napi(struct bnx2 *bp)
+{
+       int i;
+
+       for (i = 0; i < bp->irq_nvecs; i++)
+               netif_napi_del(&bp->bnx2_napi[i].napi);
+}
+
+static void
 bnx2_init_napi(struct bnx2 *bp)
 {
        int i;
index 8af8442c694a69c2e4e5dea49ebcd7d13a4e92de..af753936e835840ac0127ea78f6421893887b37d 100644 (file)
@@ -73,7 +73,7 @@ static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
        else
                *mscan_clksrc = MSCAN_CLKSRC_XTAL;
 
-       freq = mpc5xxx_get_bus_frequency(ofdev->node);
+       freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
        if (!freq)
                return 0;
 
@@ -152,7 +152,7 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev,
        }
 
        /* Determine the MSCAN device index from the physical address */
-       pval = of_get_property(ofdev->node, "reg", &plen);
+       pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
        BUG_ON(!pval || plen < sizeof(*pval));
        clockidx = (*pval & 0x80) ? 1 : 0;
        if (*pval & 0x2000)
@@ -168,11 +168,11 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev,
         */
        if (clock_name && !strcmp(clock_name, "ip")) {
                *mscan_clksrc = MSCAN_CLKSRC_IPS;
-               freq = mpc5xxx_get_bus_frequency(ofdev->node);
+               freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
        } else {
                *mscan_clksrc = MSCAN_CLKSRC_BUS;
 
-               pval = of_get_property(ofdev->node,
+               pval = of_get_property(ofdev->dev.of_node,
                                       "fsl,mscan-clock-divider", &plen);
                if (pval && plen == sizeof(*pval))
                        clockdiv = *pval;
@@ -251,7 +251,7 @@ static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
                                       const struct of_device_id *id)
 {
        struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data;
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct net_device *dev;
        struct mscan_priv *priv;
        void __iomem *base;
index fe925663d39a535a5c9d2c6f65866c3f2f29e6d7..80471269977adefdaae7e0a7845611a2e1e7cadc 100644 (file)
@@ -3919,8 +3919,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
                HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS;
        context->cstorm_st_context.status_block_id = BNX2X_DEF_SB_ID;
 
-       context->xstorm_st_context.statistics_data = (cli |
-                               XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE);
+       if (cli < MAX_X_STAT_COUNTER_ID)
+               context->xstorm_st_context.statistics_data = cli |
+                               XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE;
 
        context->xstorm_ag_context.cdu_reserved =
                CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func),
@@ -3928,10 +3929,12 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
                                        ETH_CONNECTION_TYPE);
 
        /* reset xstorm per client statistics */
-       val = BAR_XSTRORM_INTMEM +
-             XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-       for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
-               CNIC_WR(dev, val + i * 4, 0);
+       if (cli < MAX_X_STAT_COUNTER_ID) {
+               val = BAR_XSTRORM_INTMEM +
+                     XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+               for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
+                       CNIC_WR(dev, val + i * 4, 0);
+       }
 
        cp->tx_cons_ptr =
                &cp->bnx2x_def_status_blk->c_def_status_block.index_values[
@@ -3978,9 +3981,11 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
                                                BNX2X_ISCSI_RX_SB_INDEX_NUM;
        context->ustorm_st_context.common.clientId = cli;
        context->ustorm_st_context.common.status_block_id = BNX2X_DEF_SB_ID;
-       context->ustorm_st_context.common.flags =
-               USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
-       context->ustorm_st_context.common.statistics_counter_id = cli;
+       if (cli < MAX_U_STAT_COUNTER_ID) {
+               context->ustorm_st_context.common.flags =
+                       USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
+               context->ustorm_st_context.common.statistics_counter_id = cli;
+       }
        context->ustorm_st_context.common.mc_alignment_log_size = 0;
        context->ustorm_st_context.common.bd_buff_size =
                                                cp->l2_single_buf_size;
@@ -4011,10 +4016,13 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
 
        /* client tstorm info */
        tstorm_client.mtu = cp->l2_single_buf_size - 14;
-       tstorm_client.config_flags =
-                       (TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE |
-                       TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE);
-       tstorm_client.statistics_counter_id = cli;
+       tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE;
+
+       if (cli < MAX_T_STAT_COUNTER_ID) {
+               tstorm_client.config_flags |=
+                               TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
+               tstorm_client.statistics_counter_id = cli;
+       }
 
        CNIC_WR(dev, BAR_TSTRORM_INTMEM +
                   TSTORM_CLIENT_CONFIG_OFFSET(port, cli),
@@ -4024,16 +4032,21 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
                   ((u32 *)&tstorm_client)[1]);
 
        /* reset tstorm per client statistics */
-       val = BAR_TSTRORM_INTMEM +
-             TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-       for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
-               CNIC_WR(dev, val + i * 4, 0);
+       if (cli < MAX_T_STAT_COUNTER_ID) {
+
+               val = BAR_TSTRORM_INTMEM +
+                     TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+               for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
+                       CNIC_WR(dev, val + i * 4, 0);
+       }
 
        /* reset ustorm per client statistics */
-       val = BAR_USTRORM_INTMEM +
-             USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-       for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
-               CNIC_WR(dev, val + i * 4, 0);
+       if (cli < MAX_U_STAT_COUNTER_ID) {
+               val = BAR_USTRORM_INTMEM +
+                     USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+               for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
+                       CNIC_WR(dev, val + i * 4, 0);
+       }
 
        cp->rx_cons_ptr =
                &cp->bnx2x_def_status_blk->u_def_status_block.index_values[
index 3c58db5952852ad5319741c7135e452e2ad086a0..23786ee34beded0a9ae6d2c0484ca75965eeab93 100644 (file)
@@ -1181,7 +1181,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
                if (netif_msg_drv(priv))
                        printk(KERN_ERR "%s: Could not attach to PHY\n",
                               dev->name);
-               return PTR_ERR(priv->phy);
+               rc = PTR_ERR(priv->phy);
+               goto fail;
        }
 
        if ((rc = register_netdev(dev))) {
index ebdea0891665dbb81fbd6e7894abc4e97b6fd2c4..68a80893dce1daa492c23f6a7e6e0dd290645046 100644 (file)
@@ -1047,15 +1047,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
                goto err_register;
 
        /* print bus type/speed/width info */
-       e_info("(PCI%s:%s:%s) ",
-               ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
-               ((hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
-                (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
-                (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
-                (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
-               ((hw->bus_width == e1000_bus_width_64) ? "64-bit" : "32-bit"));
-
-       e_info("%pM\n", netdev->dev_addr);
+       e_info("(PCI%s:%dMHz:%d-bit) %pM\n",
+              ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
+              ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
+               (hw->bus_speed == e1000_bus_speed_120) ? 120 :
+               (hw->bus_speed == e1000_bus_speed_100) ? 100 :
+               (hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
+              ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
+              netdev->dev_addr);
 
        /* carrier off reporting is important to ethtool even BEFORE open */
        netif_carrier_off(netdev);
index 24507f3b8b1708755e0631d9c28be2fe08f67493..57a7e41da69e91e64d547362d04c7495d907f567 100644 (file)
@@ -2554,7 +2554,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
                        mdef = er32(MDEF(i));
 
                        /* Ignore filters with anything other than IPMI ports */
-                       if (mdef & !(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
+                       if (mdef & ~(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
                                continue;
 
                        /* Enable this decision filter in MANC2H */
index 0630980a27222ce31ab4bb77d8af754d5ddc0c09..0060e422f171bda3c385ef757fce13ee39d0a517 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ehea"
-#define DRV_VERSION    "EHEA_0103"
+#define DRV_VERSION    "EHEA_0105"
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
index f547894ff48fc3a02317548dafe8ec900e5044e2..8b92acb448c2691e7d2ca4de669c61e4a33677e9 100644 (file)
@@ -867,6 +867,7 @@ static int ehea_poll(struct napi_struct *napi, int budget)
                ehea_reset_cq_ep(pr->send_cq);
                ehea_reset_cq_n1(pr->recv_cq);
                ehea_reset_cq_n1(pr->send_cq);
+               rmb();
                cqe = ehea_poll_rq1(pr->qp, &wqe_index);
                cqe_skb = ehea_poll_cq(pr->send_cq);
 
@@ -2859,6 +2860,7 @@ static void ehea_reset_port(struct work_struct *work)
                container_of(work, struct ehea_port, reset_task);
        struct net_device *dev = port->netdev;
 
+       mutex_lock(&dlpar_mem_lock);
        port->resets++;
        mutex_lock(&port->port_lock);
        netif_stop_queue(dev);
@@ -2881,6 +2883,7 @@ static void ehea_reset_port(struct work_struct *work)
        netif_wake_queue(dev);
 out:
        mutex_unlock(&port->port_lock);
+       mutex_unlock(&dlpar_mem_lock);
 }
 
 static void ehea_rereg_mrs(struct work_struct *work)
@@ -3542,10 +3545,7 @@ static int ehea_mem_notifier(struct notifier_block *nb,
        int ret = NOTIFY_BAD;
        struct memory_notify *arg = data;
 
-       if (!mutex_trylock(&dlpar_mem_lock)) {
-               ehea_info("ehea_mem_notifier must not be called parallelized");
-               goto out;
-       }
+       mutex_lock(&dlpar_mem_lock);
 
        switch (action) {
        case MEM_CANCEL_OFFLINE:
@@ -3574,7 +3574,6 @@ static int ehea_mem_notifier(struct notifier_block *nb,
 
 out_unlock:
        mutex_unlock(&dlpar_mem_lock);
-out:
        return ret;
 }
 
index 85f2a2e7030aa2e1962385f9c8e92a04e1aaa29d..45e86d1e5b1b29545371a7a1129fbb99f94cfb40 100644 (file)
@@ -74,7 +74,14 @@ struct enic_msix_entry {
        void *devid;
 };
 
+#define ENIC_SET_APPLIED               (1 << 0)
+#define ENIC_SET_REQUEST               (1 << 1)
+#define ENIC_SET_NAME                  (1 << 2)
+#define ENIC_SET_INSTANCE              (1 << 3)
+#define ENIC_SET_HOST                  (1 << 4)
+
 struct enic_port_profile {
+       u32 set;
        u8 request;
        char name[PORT_PROFILE_MAX];
        u8 instance_uuid[PORT_UUID_MAX];
index 6586b5c7e4b617066bea1d652f175b51b5f9d6f4..bc7d6b96de3dec39ca96b369a6656ec22ab04a12 100644 (file)
@@ -1029,8 +1029,7 @@ static int enic_dev_init_done(struct enic *enic, int *done, int *error)
        return err;
 }
 
-static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
-       char *name, u8 *instance_uuid, u8 *host_uuid)
+static int enic_set_port_profile(struct enic *enic, u8 *mac)
 {
        struct vic_provinfo *vp;
        u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
@@ -1040,97 +1039,112 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
                "%02X%02X-%02X%02X%02X%02X%0X%02X";
        int err;
 
-       if (!name)
-               return -EINVAL;
+       err = enic_vnic_dev_deinit(enic);
+       if (err)
+               return err;
 
-       if (!is_valid_ether_addr(mac))
-               return -EADDRNOTAVAIL;
+       switch (enic->pp.request) {
 
-       vp = vic_provinfo_alloc(GFP_KERNEL, oui, VIC_PROVINFO_LINUX_TYPE);
-       if (!vp)
-               return -ENOMEM;
+       case PORT_REQUEST_ASSOCIATE:
 
-       vic_provinfo_add_tlv(vp,
-               VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
-               strlen(name) + 1, name);
-
-       vic_provinfo_add_tlv(vp,
-               VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
-               ETH_ALEN, mac);
-
-       if (instance_uuid) {
-               uuid = instance_uuid;
-               sprintf(uuid_str, uuid_fmt,
-                       uuid[0],  uuid[1],  uuid[2],  uuid[3],
-                       uuid[4],  uuid[5],  uuid[6],  uuid[7],
-                       uuid[8],  uuid[9],  uuid[10], uuid[11],
-                       uuid[12], uuid[13], uuid[14], uuid[15]);
-               vic_provinfo_add_tlv(vp,
-                       VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
-                       sizeof(uuid_str), uuid_str);
-       }
+               if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name))
+                       return -EINVAL;
 
-       if (host_uuid) {
-               uuid = host_uuid;
-               sprintf(uuid_str, uuid_fmt,
-                       uuid[0],  uuid[1],  uuid[2],  uuid[3],
-                       uuid[4],  uuid[5],  uuid[6],  uuid[7],
-                       uuid[8],  uuid[9],  uuid[10], uuid[11],
-                       uuid[12], uuid[13], uuid[14], uuid[15]);
-               vic_provinfo_add_tlv(vp,
-                       VIC_LINUX_PROV_TLV_HOST_UUID_STR,
-                       sizeof(uuid_str), uuid_str);
-       }
+               if (!is_valid_ether_addr(mac))
+                       return -EADDRNOTAVAIL;
 
-       err = enic_vnic_dev_deinit(enic);
-       if (err)
-               goto err_out;
+               vp = vic_provinfo_alloc(GFP_KERNEL, oui,
+                       VIC_PROVINFO_LINUX_TYPE);
+               if (!vp)
+                       return -ENOMEM;
 
-       memset(&enic->pp, 0, sizeof(enic->pp));
+               vic_provinfo_add_tlv(vp,
+                       VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
+                       strlen(enic->pp.name) + 1, enic->pp.name);
 
-       err = enic_dev_init_prov(enic, vp);
-       if (err)
-               goto err_out;
+               vic_provinfo_add_tlv(vp,
+                       VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
+                       ETH_ALEN, mac);
+
+               if (enic->pp.set & ENIC_SET_INSTANCE) {
+                       uuid = enic->pp.instance_uuid;
+                       sprintf(uuid_str, uuid_fmt,
+                               uuid[0],  uuid[1],  uuid[2],  uuid[3],
+                               uuid[4],  uuid[5],  uuid[6],  uuid[7],
+                               uuid[8],  uuid[9],  uuid[10], uuid[11],
+                               uuid[12], uuid[13], uuid[14], uuid[15]);
+                       vic_provinfo_add_tlv(vp,
+                               VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
+                               sizeof(uuid_str), uuid_str);
+               }
 
-       enic->pp.request = request;
-       memcpy(enic->pp.name, name, PORT_PROFILE_MAX);
-       if (instance_uuid)
-               memcpy(enic->pp.instance_uuid,
-                       instance_uuid, PORT_UUID_MAX);
-       if (host_uuid)
-               memcpy(enic->pp.host_uuid,
-                       host_uuid, PORT_UUID_MAX);
+               if (enic->pp.set & ENIC_SET_HOST) {
+                       uuid = enic->pp.host_uuid;
+                       sprintf(uuid_str, uuid_fmt,
+                               uuid[0],  uuid[1],  uuid[2],  uuid[3],
+                               uuid[4],  uuid[5],  uuid[6],  uuid[7],
+                               uuid[8],  uuid[9],  uuid[10], uuid[11],
+                               uuid[12], uuid[13], uuid[14], uuid[15]);
+                       vic_provinfo_add_tlv(vp,
+                               VIC_LINUX_PROV_TLV_HOST_UUID_STR,
+                               sizeof(uuid_str), uuid_str);
+               }
 
-err_out:
-       vic_provinfo_free(vp);
+               err = enic_dev_init_prov(enic, vp);
+               vic_provinfo_free(vp);
+               if (err)
+                       return err;
+               break;
 
-       return err;
-}
+       case PORT_REQUEST_DISASSOCIATE:
+               break;
 
-static int enic_unset_port_profile(struct enic *enic)
-{
-       memset(&enic->pp, 0, sizeof(enic->pp));
-       return enic_vnic_dev_deinit(enic);
+       default:
+               return -EINVAL;
+       }
+
+       enic->pp.set |= ENIC_SET_APPLIED;
+       return 0;
 }
 
 static int enic_set_vf_port(struct net_device *netdev, int vf,
        struct nlattr *port[])
 {
        struct enic *enic = netdev_priv(netdev);
-       char *name = NULL;
-       u8 *instance_uuid = NULL;
-       u8 *host_uuid = NULL;
-       u8 request = PORT_REQUEST_DISASSOCIATE;
+
+       memset(&enic->pp, 0, sizeof(enic->pp));
+
+       if (port[IFLA_PORT_REQUEST]) {
+               enic->pp.set |= ENIC_SET_REQUEST;
+               enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
+       }
+
+       if (port[IFLA_PORT_PROFILE]) {
+               enic->pp.set |= ENIC_SET_NAME;
+               memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]),
+                       PORT_PROFILE_MAX);
+       }
+
+       if (port[IFLA_PORT_INSTANCE_UUID]) {
+               enic->pp.set |= ENIC_SET_INSTANCE;
+               memcpy(enic->pp.instance_uuid,
+                       nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX);
+       }
+
+       if (port[IFLA_PORT_HOST_UUID]) {
+               enic->pp.set |= ENIC_SET_HOST;
+               memcpy(enic->pp.host_uuid,
+                       nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
+       }
 
        /* don't support VFs, yet */
        if (vf != PORT_SELF_VF)
                return -EOPNOTSUPP;
 
-       if (port[IFLA_PORT_REQUEST])
-               request = nla_get_u8(port[IFLA_PORT_REQUEST]);
+       if (!(enic->pp.set & ENIC_SET_REQUEST))
+               return -EOPNOTSUPP;
 
-       switch (request) {
-       case PORT_REQUEST_ASSOCIATE:
+       if (enic->pp.request == PORT_REQUEST_ASSOCIATE) {
 
                /* If the interface mac addr hasn't been assigned,
                 * assign a random mac addr before setting port-
@@ -1139,30 +1153,9 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
 
                if (is_zero_ether_addr(netdev->dev_addr))
                        random_ether_addr(netdev->dev_addr);
-
-               if (port[IFLA_PORT_PROFILE])
-                       name = nla_data(port[IFLA_PORT_PROFILE]);
-
-               if (port[IFLA_PORT_INSTANCE_UUID])
-                       instance_uuid =
-                               nla_data(port[IFLA_PORT_INSTANCE_UUID]);
-
-               if (port[IFLA_PORT_HOST_UUID])
-                       host_uuid = nla_data(port[IFLA_PORT_HOST_UUID]);
-
-               return enic_set_port_profile(enic, request,
-                       netdev->dev_addr, name,
-                       instance_uuid, host_uuid);
-
-       case PORT_REQUEST_DISASSOCIATE:
-
-               return enic_unset_port_profile(enic);
-
-       default:
-               break;
        }
 
-       return -EOPNOTSUPP;
+       return enic_set_port_profile(enic, netdev->dev_addr);
 }
 
 static int enic_get_vf_port(struct net_device *netdev, int vf,
@@ -1172,14 +1165,12 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
        int err, error, done;
        u16 response = PORT_PROFILE_RESPONSE_SUCCESS;
 
-       /* don't support VFs, yet */
-       if (vf != PORT_SELF_VF)
-               return -EOPNOTSUPP;
+       if (!(enic->pp.set & ENIC_SET_APPLIED))
+               return -ENODATA;
 
        err = enic_dev_init_done(enic, &done, &error);
-
        if (err)
-               return err;
+               error = err;
 
        switch (error) {
        case ERR_SUCCESS:
@@ -1202,12 +1193,15 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
 
        NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request);
        NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response);
-       NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
-               enic->pp.name);
-       NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
-               enic->pp.instance_uuid);
-       NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
-               enic->pp.host_uuid);
+       if (enic->pp.set & ENIC_SET_NAME)
+               NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
+                       enic->pp.name);
+       if (enic->pp.set & ENIC_SET_INSTANCE)
+               NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
+                       enic->pp.instance_uuid);
+       if (enic->pp.set & ENIC_SET_HOST)
+               NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
+                       enic->pp.host_uuid);
 
        return 0;
 
index 2b3e16db5c82f2a75763f128854b06a3d2447d24..e0d33281ec980b6013dea7c1632b19358af7d30c 100644 (file)
@@ -709,7 +709,7 @@ int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len)
 {
        u64 a0, a1 = len;
        int wait = 1000;
-       u64 prov_pa;
+       dma_addr_t prov_pa;
        void *prov_buf;
        int ret;
 
index 6838dfc9ef23a4549c69144c7d87db589e1c7928..4c274657283c36ad2157d5874447e3c434483869 100644 (file)
@@ -87,6 +87,7 @@ static int rx_copybreak;
 #include <linux/bitops.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
+#include <asm/byteorder.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
@@ -230,7 +231,7 @@ static const u16 media2miictl[16] = {
  * The EPIC100 Rx and Tx buffer descriptors.  Note that these
  * really ARE host-endian; it's not a misannotation.  We tell
  * the card to byteswap them internally on big-endian hosts -
- * look for #ifdef CONFIG_BIG_ENDIAN in epic_open().
+ * look for #ifdef __BIG_ENDIAN in epic_open().
  */
 
 struct epic_tx_desc {
@@ -690,7 +691,7 @@ static int epic_open(struct net_device *dev)
                outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
        /* Tell the chip to byteswap descriptors on big-endian hosts */
-#ifdef CONFIG_BIG_ENDIAN
+#ifdef __BIG_ENDIAN
        outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
        inl(ioaddr + GENCTL);
        outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
@@ -806,7 +807,7 @@ static void epic_restart(struct net_device *dev)
        for (i = 16; i > 0; i--)
                outl(0x0008, ioaddr + TEST1);
 
-#ifdef CONFIG_BIG_ENDIAN
+#ifdef __BIG_ENDIAN
        outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
 #else
        outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
index ddf7a86cd4661f0cdfa438d7a2a9dae6db68acec..edfff92a6d8ebd8c141b9697b216efccfbbec226 100644 (file)
@@ -1373,10 +1373,9 @@ fec_suspend(struct platform_device *dev, pm_message_t state)
 
        if (ndev) {
                fep = netdev_priv(ndev);
-               if (netif_running(ndev)) {
-                       netif_device_detach(ndev);
-                       fec_stop(ndev);
-               }
+               if (netif_running(ndev))
+                       fec_enet_close(ndev);
+               clk_disable(fep->clk);
        }
        return 0;
 }
@@ -1385,12 +1384,13 @@ static int
 fec_resume(struct platform_device *dev)
 {
        struct net_device *ndev = platform_get_drvdata(dev);
+       struct fec_enet_private *fep;
 
        if (ndev) {
-               if (netif_running(ndev)) {
-                       fec_enet_init(ndev, 0);
-                       netif_device_attach(ndev);
-               }
+               fep = netdev_priv(ndev);
+               clk_enable(fep->clk);
+               if (netif_running(ndev))
+                       fec_enet_open(ndev);
        }
        return 0;
 }
index 5d45084b287d13afa6d24dcfc02d18f56afb0ce1..48e91b6242ce99b8382aeb4d55ec17c3af682cc7 100644 (file)
@@ -504,17 +504,54 @@ static int get_regs_len(struct net_device *dev)
 }
 
 /* Some transmit errors cause the transmitter to shut
- * down.  We now issue a restart transmit.  Since the
- * errors close the BD and update the pointers, the restart
- * _should_ pick up without having to reset any of our
- * pointers either.  Also, To workaround 8260 device erratum
- * CPM37, we must disable and then re-enable the transmitter
- * following a Late Collision, Underrun, or Retry Limit error.
+ * down.  We now issue a restart transmit.
+ * Also, to workaround 8260 device erratum CPM37, we must
+ * disable and then re-enable the transmitterfollowing a
+ * Late Collision, Underrun, or Retry Limit error.
+ * In addition, tbptr may point beyond BDs beyond still marked
+ * as ready due to internal pipelining, so we need to look back
+ * through the BDs and adjust tbptr to point to the last BD
+ * marked as ready.  This may result in some buffers being
+ * retransmitted.
  */
 static void tx_restart(struct net_device *dev)
 {
        struct fs_enet_private *fep = netdev_priv(dev);
        fcc_t __iomem *fccp = fep->fcc.fccp;
+       const struct fs_platform_info *fpi = fep->fpi;
+       fcc_enet_t __iomem *ep = fep->fcc.ep;
+       cbd_t __iomem *curr_tbptr;
+       cbd_t __iomem *recheck_bd;
+       cbd_t __iomem *prev_bd;
+       cbd_t __iomem *last_tx_bd;
+
+       last_tx_bd = fep->tx_bd_base + (fpi->tx_ring * sizeof(cbd_t));
+
+       /* get the current bd held in TBPTR  and scan back from this point */
+       recheck_bd = curr_tbptr = (cbd_t __iomem *)
+               ((R32(ep, fen_genfcc.fcc_tbptr) - fep->ring_mem_addr) +
+               fep->ring_base);
+
+       prev_bd = (recheck_bd == fep->tx_bd_base) ? last_tx_bd : recheck_bd - 1;
+
+       /* Move through the bds in reverse, look for the earliest buffer
+        * that is not ready.  Adjust TBPTR to the following buffer */
+       while ((CBDR_SC(prev_bd) & BD_ENET_TX_READY) != 0) {
+               /* Go back one buffer */
+               recheck_bd = prev_bd;
+
+               /* update the previous buffer */
+               prev_bd = (prev_bd == fep->tx_bd_base) ? last_tx_bd : prev_bd - 1;
+
+               /* We should never see all bds marked as ready, check anyway */
+               if (recheck_bd == curr_tbptr)
+                       break;
+       }
+       /* Now update the TBPTR and dirty flag to the current buffer */
+       W32(ep, fen_genfcc.fcc_tbptr,
+               (uint) (((void *)recheck_bd - fep->ring_base) +
+               fep->ring_mem_addr));
+       fep->dirty_tx = recheck_bd;
 
        C32(fccp, fcc_gfmr, FCC_GFMR_ENT);
        udelay(10);
index 0f90685d3d19472e3bc0dc9b05ed5872a5fa9f63..3607340f3da7ce93a671a964366758780f7bc038 100644 (file)
@@ -169,7 +169,7 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
 
        new_bus->name = "CPM2 Bitbanged MII",
 
-       ret = fs_mii_bitbang_init(new_bus, ofdev->node);
+       ret = fs_mii_bitbang_init(new_bus, ofdev->dev.of_node);
        if (ret)
                goto out_free_bus;
 
@@ -181,7 +181,7 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
        new_bus->parent = &ofdev->dev;
        dev_set_drvdata(&ofdev->dev, new_bus);
 
-       ret = of_mdiobus_register(new_bus, ofdev->node);
+       ret = of_mdiobus_register(new_bus, ofdev->dev.of_node);
        if (ret)
                goto out_free_irqs;
 
index 1830f3199cb523080b1a880dd5e834ad9fb8d99a..28b53d1cd4f168701fa4ce41a7c5e0edbaa6f783 100644 (file)
@@ -381,10 +381,14 @@ static void gfar_init_mac(struct net_device *ndev)
        /* Insert receive time stamps into padding alignment bytes */
        if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {
                rctrl &= ~RCTRL_PAL_MASK;
-               rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE | RCTRL_PADDING(8);
+               rctrl |= RCTRL_PADDING(8);
                priv->padding = 8;
        }
 
+       /* Enable HW time stamping if requested from user space */
+       if (priv->hwts_rx_en)
+               rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
+
        /* keep vlan related bits if it's enabled */
        if (priv->vlgrp) {
                rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
@@ -806,12 +810,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev,
 
        switch (config.rx_filter) {
        case HWTSTAMP_FILTER_NONE:
-               priv->hwts_rx_en = 0;
+               if (priv->hwts_rx_en) {
+                       stop_gfar(netdev);
+                       priv->hwts_rx_en = 0;
+                       startup_gfar(netdev);
+               }
                break;
        default:
                if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))
                        return -ERANGE;
-               priv->hwts_rx_en = 1;
+               if (!priv->hwts_rx_en) {
+                       stop_gfar(netdev);
+                       priv->hwts_rx_en = 1;
+                       startup_gfar(netdev);
+               }
                config.rx_filter = HWTSTAMP_FILTER_ALL;
                break;
        }
@@ -2643,6 +2655,10 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
                dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
                                priv->rx_buffer_size, DMA_FROM_DEVICE);
 
+               if (unlikely(!(bdp->status & RXBD_ERR) &&
+                               bdp->length > priv->rx_buffer_size))
+                       bdp->status = RXBD_LARGE;
+
                /* We drop the frame if we failed to allocate a new buffer */
                if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
                                 bdp->status & RXBD_ERR)) {
index f37a4c143ddddf985556018dc5e21288e23f3207..3a029d02c2b410405dd37c5e6b1b7e8e4ccb63c9 100644 (file)
@@ -1607,14 +1607,13 @@ static struct of_device_id greth_of_match[] = {
 MODULE_DEVICE_TABLE(of, greth_of_match);
 
 static struct of_platform_driver greth_of_driver = {
-       .name = "grlib-greth",
-       .match_table = greth_of_match,
+       .driver = {
+               .name = "grlib-greth",
+               .owner = THIS_MODULE,
+               .of_match_table = greth_of_match,
+       },
        .probe = greth_of_probe,
        .remove = __devexit_p(greth_of_remove),
-       .driver = {
-                  .owner = THIS_MODULE,
-                  .name = "grlib-greth",
-                  },
 };
 
 static int __init greth_init(void)
index 1159d9138f0577c84643ba3db8b263d995cd683a..9595b1bfb8dd54edab12c60fcf0bace4a19d1d1f 100644 (file)
@@ -1188,6 +1188,7 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
                IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
        } else {
                hw_dbg(hw, "RAR index %d is out of range.\n", index);
+               return IXGBE_ERR_RAR_INDEX;
        }
 
        return 0;
@@ -1219,6 +1220,7 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
                IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
        } else {
                hw_dbg(hw, "RAR index %d is out of range.\n", index);
+               return IXGBE_ERR_RAR_INDEX;
        }
 
        /* clear VMDq pool/queue selection for this RAR */
index c50a7541ffecf763fb0050de183f4db98f43b1b7..3a93a81872b87153404111152bf5860307815772 100644 (file)
@@ -2077,25 +2077,6 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
        return 0;
 }
 
-/*
- * this function must be called before setting the new value of
- * rx_itr_setting
- */
-static bool ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
-                               struct ethtool_coalesce *ec)
-{
-       /* check the old value and enable RSC if necessary */
-       if ((adapter->rx_itr_setting == 0) &&
-           (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) {
-               adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
-               adapter->netdev->features |= NETIF_F_LRO;
-               DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n",
-                       ec->rx_coalesce_usecs);
-               return true;
-       }
-       return false;
-}
-
 static int ixgbe_set_coalesce(struct net_device *netdev,
                               struct ethtool_coalesce *ec)
 {
@@ -2124,9 +2105,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                    (1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
                        return -EINVAL;
 
-               /* check the old value and enable RSC if necessary */
-               need_reset = ixgbe_reenable_rsc(adapter, ec);
-
                /* store the value in ints/second */
                adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
 
@@ -2135,9 +2113,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                /* clear the lower bit as its used for dynamic state */
                adapter->rx_itr_setting &= ~1;
        } else if (ec->rx_coalesce_usecs == 1) {
-               /* check the old value and enable RSC if necessary */
-               need_reset = ixgbe_reenable_rsc(adapter, ec);
-
                /* 1 means dynamic mode */
                adapter->rx_eitr_param = 20000;
                adapter->rx_itr_setting = 1;
@@ -2157,10 +2132,11 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                 */
                if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
                        adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
-                       netdev->features &= ~NETIF_F_LRO;
-                       DPRINTK(PROBE, INFO,
-                               "rx-usecs set to 0, disabling RSC\n");
-
+                       if (netdev->features & NETIF_F_LRO) {
+                               netdev->features &= ~NETIF_F_LRO;
+                               DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+                                       "disabling LRO/RSC\n");
+                       }
                        need_reset = true;
                }
        }
@@ -2255,6 +2231,9 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
                        }
                } else if (!adapter->rx_itr_setting) {
                        netdev->features &= ~ETH_FLAG_LRO;
+                       if (data & ETH_FLAG_LRO)
+                               DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+                                       "LRO/RSC cannot be enabled.\n");
                }
        }
 
index d571d101de08fb4c183af77cb9b64d10904d10a7..ce30c62a97f70bd08f3d4bdbcb6009dda523ff0e 100644 (file)
@@ -642,7 +642,7 @@ static inline bool ixgbe_tx_xon_state(struct ixgbe_adapter *adapter,
        u32 txoff = IXGBE_TFCS_TXOFF;
 
 #ifdef CONFIG_IXGBE_DCB
-       if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+       if (adapter->dcb_cfg.pfc_mode_enable) {
                int tc;
                int reg_idx = tx_ring->reg_idx;
                int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
@@ -5282,6 +5282,10 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
        u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
        u64 non_eop_descs = 0, restart_queue = 0;
 
+       if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+           test_bit(__IXGBE_RESETTING, &adapter->state))
+               return;
+
        if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
                u64 rsc_count = 0;
                u64 rsc_flush = 0;
index 09e1911ff510474ecda600446a51330d057647e3..48325a5beff2054c59b2aa9f6b333bcdf4d3d0c8 100644 (file)
@@ -575,6 +575,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                 * 4    SFP_DA_CORE1 - 82599-specific
                 * 5    SFP_SR/LR_CORE0 - 82599-specific
                 * 6    SFP_SR/LR_CORE1 - 82599-specific
+                * 7    SFP_act_lmt_DA_CORE0 - 82599-specific
+                * 8    SFP_act_lmt_DA_CORE1 - 82599-specific
                 */
                if (hw->mac.type == ixgbe_mac_82598EB) {
                        if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
index 2eb6e151016cac10ca15eadfd9311283361e09b9..cdd1998f18c705348a618098f8e098edda8d7e98 100644 (file)
@@ -2609,6 +2609,7 @@ struct ixgbe_info {
 #define IXGBE_ERR_EEPROM_VERSION                -24
 #define IXGBE_ERR_NO_SPACE                      -25
 #define IXGBE_ERR_OVERTEMP                      -26
+#define IXGBE_ERR_RAR_INDEX                     -27
 #define IXGBE_NOT_IMPLEMENTED                   0x7FFFFFFF
 
 #endif /* _IXGBE_TYPE_H_ */
index 26bf1b76b9977a1510bf3407c34322bed46512ba..c7a9bef4dfb0890001c5243211862def6a4de2a6 100644 (file)
@@ -135,6 +135,7 @@ struct korina_private {
        struct napi_struct napi;
        struct timer_list media_check_timer;
        struct mii_if_info mii_if;
+       struct work_struct restart_task;
        struct net_device *dev;
        int phy_addr;
 };
@@ -375,7 +376,7 @@ static int korina_rx(struct net_device *dev, int limit)
                if (devcs & ETH_RX_LE)
                        dev->stats.rx_length_errors++;
                if (devcs & ETH_RX_OVR)
-                       dev->stats.rx_over_errors++;
+                       dev->stats.rx_fifo_errors++;
                if (devcs & ETH_RX_CV)
                        dev->stats.rx_frame_errors++;
                if (devcs & ETH_RX_CES)
@@ -764,10 +765,9 @@ static int korina_alloc_ring(struct net_device *dev)
 
        /* Initialize the receive descriptors */
        for (i = 0; i < KORINA_NUM_RDS; i++) {
-               skb = dev_alloc_skb(KORINA_RBSIZE + 2);
+               skb = netdev_alloc_skb_ip_align(dev, KORINA_RBSIZE);
                if (!skb)
                        return -ENOMEM;
-               skb_reserve(skb, 2);
                lp->rx_skb[i] = skb;
                lp->rd_ring[i].control = DMA_DESC_IOD |
                                DMA_COUNT(KORINA_RBSIZE);
@@ -890,12 +890,12 @@ static int korina_init(struct net_device *dev)
 
 /*
  * Restart the RC32434 ethernet controller.
- * FIXME: check the return status where we call it
  */
-static int korina_restart(struct net_device *dev)
+static void korina_restart_task(struct work_struct *work)
 {
-       struct korina_private *lp = netdev_priv(dev);
-       int ret;
+       struct korina_private *lp = container_of(work,
+                       struct korina_private, restart_task);
+       struct net_device *dev = lp->dev;
 
        /*
         * Disable interrupts
@@ -916,10 +916,9 @@ static int korina_restart(struct net_device *dev)
 
        napi_disable(&lp->napi);
 
-       ret = korina_init(dev);
-       if (ret < 0) {
+       if (korina_init(dev) < 0) {
                printk(KERN_ERR "%s: cannot restart device\n", dev->name);
-               return ret;
+               return;
        }
        korina_multicast_list(dev);
 
@@ -927,8 +926,6 @@ static int korina_restart(struct net_device *dev)
        enable_irq(lp->ovr_irq);
        enable_irq(lp->tx_irq);
        enable_irq(lp->rx_irq);
-
-       return ret;
 }
 
 static void korina_clear_and_restart(struct net_device *dev, u32 value)
@@ -937,7 +934,7 @@ static void korina_clear_and_restart(struct net_device *dev, u32 value)
 
        netif_stop_queue(dev);
        writel(value, &lp->eth_regs->ethintfc);
-       korina_restart(dev);
+       schedule_work(&lp->restart_task);
 }
 
 /* Ethernet Tx Underflow interrupt */
@@ -962,11 +959,8 @@ static irqreturn_t korina_und_interrupt(int irq, void *dev_id)
 static void korina_tx_timeout(struct net_device *dev)
 {
        struct korina_private *lp = netdev_priv(dev);
-       unsigned long flags;
 
-       spin_lock_irqsave(&lp->lock, flags);
-       korina_restart(dev);
-       spin_unlock_irqrestore(&lp->lock, flags);
+       schedule_work(&lp->restart_task);
 }
 
 /* Ethernet Rx Overflow interrupt */
@@ -1086,6 +1080,8 @@ static int korina_close(struct net_device *dev)
 
        napi_disable(&lp->napi);
 
+       cancel_work_sync(&lp->restart_task);
+
        free_irq(lp->rx_irq, dev);
        free_irq(lp->tx_irq, dev);
        free_irq(lp->ovr_irq, dev);
@@ -1198,6 +1194,8 @@ static int korina_probe(struct platform_device *pdev)
        }
        setup_timer(&lp->media_check_timer, korina_poll_media, (unsigned long) dev);
 
+       INIT_WORK(&lp->restart_task, korina_restart_task);
+
        printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n",
                        dev->name);
 out:
index c80ca64277b224934bc57e1b541c7cef7193a9ff..7805bbf1d53a6ceeaf02f8c68f4e3740e2c4939d 100644 (file)
@@ -4854,7 +4854,7 @@ static inline void copy_old_skb(struct sk_buff *old, struct sk_buff *skb)
  *
  * Return 0 if successful; otherwise an error code indicating failure.
  */
-static int netdev_tx(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev)
 {
        struct dev_priv *priv = netdev_priv(dev);
        struct dev_info *hw_priv = priv->adapter;
@@ -6863,6 +6863,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_tx_timeout         = netdev_tx_timeout,
        .ndo_change_mtu         = netdev_change_mtu,
        .ndo_set_mac_address    = netdev_set_mac_address,
+       .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = netdev_ioctl,
        .ndo_set_rx_mode        = netdev_set_rx_mode,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index ce5d6e9092182a43d2f0660e68667edf44bfae3b..c27f4291b350422978ab9fbf55bd6318ec0953ae 100644 (file)
@@ -1343,7 +1343,7 @@ static void set_multicast_list(struct net_device *dev)
        DEB(DEB_MULTI,
            printk(KERN_DEBUG
                   "%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
-                  dev->name, dev->mc_count,
+                  dev->name, netdev_mc_count(dev),
                   dev->flags & IFF_PROMISC ? "ON" : "OFF",
                   dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
 
index b6855a6476f8eaa3480135d65096c05b870ed101..1c5221f79d6faf3fdc055e728c9498f28e9f5d8d 100644 (file)
@@ -997,8 +997,11 @@ MODULE_DEVICE_TABLE (of, mace_match);
 
 static struct macio_driver mace_driver =
 {
-       .name           = "mace",
-       .match_table    = mace_match,
+       .driver = {
+               .name           = "mace",
+               .owner          = THIS_MODULE,
+               .of_match_table = mace_match,
+       },
        .probe          = mace_probe,
        .remove         = mace_remove,
 };
index 8e9704f5c12213390923cf77005df3dc63b88dd5..869f0ea43a5bbc820ae71fca9ffcb21ba6315119 100644 (file)
@@ -247,7 +247,7 @@ static const struct net_device_ops mipsnet_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __init mipsnet_probe(struct platform_device *dev)
+static int __devinit mipsnet_probe(struct platform_device *dev)
 {
        struct net_device *netdev;
        int err;
index f26e54716c886569f9e30d9a8a5c34d6056b58e6..3a41b6a84a68636a61fd85fd233a17a4c0ce3cd6 100644 (file)
@@ -629,7 +629,8 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
        if (addr == NULL) {
                dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n",
                                netdev->name);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_out_free;
        }
 
        tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
index 5c496f8d7c497f16c5a17fe7398794efdca550b3..29d7b93d0493be12e4a5def185282371b5cd400d 100644 (file)
@@ -1159,9 +1159,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
 
        window = CRB_HI(off);
 
-       if (adapter->ahw.crb_win == window)
-               return;
-
        writel(window, addr);
        if (readl(addr) != window) {
                if (printk_ratelimit())
@@ -1169,7 +1166,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
                                "failed to set CRB window to %d off 0x%lx\n",
                                window, off);
        }
-       adapter->ahw.crb_win = window;
 }
 
 static void __iomem *
index 045a7c8f5bdf8e08fd4b317a96f0917023f238d3..c865dda2adf15f8b59a579640d416099e9fabc0c 100644 (file)
@@ -218,7 +218,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
        if (cmd_buf_arr == NULL) {
                dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
                       netdev->name);
-               return -ENOMEM;
+               goto err_out;
        }
        memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
        tx_ring->cmd_buf_arr = cmd_buf_arr;
@@ -230,7 +230,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
        if (rds_ring == NULL) {
                dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n",
                       netdev->name);
-               return -ENOMEM;
+               goto err_out;
        }
        recv_ctx->rds_rings = rds_ring;
 
@@ -1805,9 +1805,10 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
        netxen_ctx_msg msg = 0;
        struct list_head *head;
 
+       spin_lock(&rds_ring->lock);
+
        producer = rds_ring->producer;
 
-       spin_lock(&rds_ring->lock);
        head = &rds_ring->free_list;
        while (!list_empty(head)) {
 
@@ -1829,7 +1830,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
 
                producer = get_next_index(producer, rds_ring->num_desc);
        }
-       spin_unlock(&rds_ring->lock);
 
        if (count) {
                rds_ring->producer = producer;
@@ -1853,6 +1853,8 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
                                        NETXEN_RCV_PRODUCER_OFFSET), msg);
                }
        }
+
+       spin_unlock(&rds_ring->lock);
 }
 
 static void
@@ -1864,10 +1866,11 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
        int producer, count = 0;
        struct list_head *head;
 
-       producer = rds_ring->producer;
        if (!spin_trylock(&rds_ring->lock))
                return;
 
+       producer = rds_ring->producer;
+
        head = &rds_ring->free_list;
        while (!list_empty(head)) {
 
index 6f77a768ba880b532dfa85521e1883a460a4bf9d..bfdef72c5d5ea6371b2fc634c9e2a8476d13fa33 100644 (file)
@@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
index 7b6fe89f9db0aa4c3f5373a25465efaf8d658ad3..307cd1721e91271bb1b3762868f9dbcb6400d218 100644 (file)
@@ -322,6 +322,7 @@ static int smc91c92_probe(struct pcmcia_device *link)
        return -ENOMEM;
     smc = netdev_priv(dev);
     smc->p_dev = link;
+    link->priv = dev;
 
     spin_lock_init(&smc->lock);
     link->io.NumPorts1 = 16;
@@ -1504,12 +1505,20 @@ irq_done:
        writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR);
        writeb(cor, smc->base + MOT_LAN + CISREG_COR);
     }
-#ifdef DOES_NOT_WORK
-    if (smc->base != NULL) { /* Megahertz MFC's */
-       readb(smc->base+MEGAHERTZ_ISR);
-       readb(smc->base+MEGAHERTZ_ISR);
+
+    if ((smc->base != NULL) &&  /* Megahertz MFC's */
+       (smc->manfid == MANFID_MEGAHERTZ) &&
+       (smc->cardid == PRODID_MEGAHERTZ_EM3288)) {
+
+       u_char tmp;
+       tmp = readb(smc->base+MEGAHERTZ_ISR);
+       tmp = readb(smc->base+MEGAHERTZ_ISR);
+
+       /* Retrigger interrupt if needed */
+       writeb(tmp, smc->base + MEGAHERTZ_ISR);
+       writeb(tmp, smc->base + MEGAHERTZ_ISR);
     }
-#endif
+
     spin_unlock(&smc->lock);
     return IRQ_RETVAL(handled);
 }
index 8ee929b796d848e5440271f92b103ff32f5c9c8d..29c39ff85de56a0012ac8be5a50508aeab56e784 100644 (file)
@@ -53,6 +53,9 @@
 
 #define MII_LXT971_ISR         19  /* Interrupt Status Register */
 
+/* register definitions for the 973 */
+#define MII_LXT973_PCR 16 /* Port Configuration Register */
+#define PCR_FIBER_SELECT 1
 
 MODULE_DESCRIPTION("Intel LXT PHY driver");
 MODULE_AUTHOR("Andy Fleming");
@@ -119,6 +122,33 @@ static int lxt971_config_intr(struct phy_device *phydev)
        return err;
 }
 
+static int lxt973_probe(struct phy_device *phydev)
+{
+       int val = phy_read(phydev, MII_LXT973_PCR);
+
+       if (val & PCR_FIBER_SELECT) {
+               /*
+                * If fiber is selected, then the only correct setting
+                * is 100Mbps, full duplex, and auto negotiation off.
+                */
+               val = phy_read(phydev, MII_BMCR);
+               val |= (BMCR_SPEED100 | BMCR_FULLDPLX);
+               val &= ~BMCR_ANENABLE;
+               phy_write(phydev, MII_BMCR, val);
+               /* Remember that the port is in fiber mode. */
+               phydev->priv = lxt973_probe;
+       } else {
+               phydev->priv = NULL;
+       }
+       return 0;
+}
+
+static int lxt973_config_aneg(struct phy_device *phydev)
+{
+       /* Do nothing if port is in fiber mode. */
+       return phydev->priv ? 0 : genphy_config_aneg(phydev);
+}
+
 static struct phy_driver lxt970_driver = {
        .phy_id         = 0x78100000,
        .name           = "LXT970",
@@ -146,6 +176,18 @@ static struct phy_driver lxt971_driver = {
        .driver         = { .owner = THIS_MODULE,},
 };
 
+static struct phy_driver lxt973_driver = {
+       .phy_id         = 0x00137a10,
+       .name           = "LXT973",
+       .phy_id_mask    = 0xfffffff0,
+       .features       = PHY_BASIC_FEATURES,
+       .flags          = 0,
+       .probe          = lxt973_probe,
+       .config_aneg    = lxt973_config_aneg,
+       .read_status    = genphy_read_status,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
 static int __init lxt_init(void)
 {
        int ret;
@@ -157,9 +199,15 @@ static int __init lxt_init(void)
        ret = phy_driver_register(&lxt971_driver);
        if (ret)
                goto err2;
+
+       ret = phy_driver_register(&lxt973_driver);
+       if (ret)
+               goto err3;
        return 0;
 
- err2: 
+ err3:
+       phy_driver_unregister(&lxt971_driver);
+ err2:
        phy_driver_unregister(&lxt970_driver);
  err1:
        return ret;
@@ -169,6 +217,7 @@ static void __exit lxt_exit(void)
 {
        phy_driver_unregister(&lxt970_driver);
        phy_driver_unregister(&lxt971_driver);
+       phy_driver_unregister(&lxt973_driver);
 }
 
 module_init(lxt_init);
@@ -177,6 +226,7 @@ module_exit(lxt_exit);
 static struct mdio_device_id lxt_tbl[] = {
        { 0x78100000, 0xfffffff0 },
        { 0x001378e0, 0xfffffff0 },
+       { 0x00137a10, 0xfffffff0 },
        { }
 };
 
index c5f8eb102bf76de12c86d2665b19b1c7fcb8d8b0..1b2c29150202080e75c2e9732b0150c204ed9161 100644 (file)
@@ -1422,7 +1422,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
                flen = len;
                if (nfree > 0) {
                        if (pch->speed == 0) {
-                               flen = totlen/nfree;
+                               flen = len/nfree;
                                if (nbigger > 0) {
                                        flen++;
                                        nbigger--;
index 217e709bda3ede440478bf2eb73c5646dd96e903..96b6cfbf0a3a682b14216fa23a9e737a48973aaa 100644 (file)
@@ -559,6 +559,11 @@ static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
                        break;
                udelay(25);
        }
+       /*
+        * According to hardware specs a 20us delay is required after write
+        * complete indication, but before sending next command.
+        */
+       udelay(20);
 }
 
 static int mdio_read(void __iomem *ioaddr, int reg_addr)
@@ -578,6 +583,12 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
                }
                udelay(25);
        }
+       /*
+        * According to hardware specs a 20us delay is required after read
+        * complete indication, but before sending next command.
+        */
+       udelay(20);
+
        return value;
 }
 
index 2e6fd89f2a72d722555357bf46595754f6426e38..4762c91cb587f03c19eddd58abef2ea449a2e941 100644 (file)
@@ -830,7 +830,7 @@ static inline const char *efx_dev_name(struct efx_nic *efx)
 
 static inline unsigned int efx_port_num(struct efx_nic *efx)
 {
-       return PCI_FUNC(efx->pci_dev->devfn);
+       return efx->net_dev->dev_id;
 }
 
 /**
index 727b4228e0819bfe336e38ed6504bd8c2d852edc..f2b1e6180753536336921b90f53f62c8675fda72 100644 (file)
@@ -206,6 +206,7 @@ static int siena_probe_nic(struct efx_nic *efx)
 {
        struct siena_nic_data *nic_data;
        bool already_attached = 0;
+       efx_oword_t reg;
        int rc;
 
        /* Allocate storage for hardware specific data */
@@ -220,6 +221,9 @@ static int siena_probe_nic(struct efx_nic *efx)
                goto fail1;
        }
 
+       efx_reado(efx, &reg, FR_AZ_CS_DEBUG);
+       efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1;
+
        efx_mcdi_init(efx);
 
        /* Recover from a failed assertion before probing */
index 2111c7bbf57831209b689871ceea4cb48a82de87..7985165e84fc4ed6ca6ce5fceb8e60d54dca0b5d 100644 (file)
@@ -717,11 +717,24 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
        sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 }
 
+/* Enable Rx/Tx */
+static void sky2_enable_rx_tx(struct sky2_port *sky2)
+{
+       struct sky2_hw *hw = sky2->hw;
+       unsigned port = sky2->port;
+       u16 reg;
+
+       reg = gma_read16(hw, port, GM_GP_CTRL);
+       reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+       gma_write16(hw, port, GM_GP_CTRL, reg);
+}
+
 /* Force a renegotiation */
 static void sky2_phy_reinit(struct sky2_port *sky2)
 {
        spin_lock_bh(&sky2->phy_lock);
        sky2_phy_init(sky2->hw, sky2->port);
+       sky2_enable_rx_tx(sky2);
        spin_unlock_bh(&sky2->phy_lock);
 }
 
@@ -2040,7 +2053,6 @@ static void sky2_link_up(struct sky2_port *sky2)
 {
        struct sky2_hw *hw = sky2->hw;
        unsigned port = sky2->port;
-       u16 reg;
        static const char *fc_name[] = {
                [FC_NONE]       = "none",
                [FC_TX]         = "tx",
@@ -2048,10 +2060,7 @@ static void sky2_link_up(struct sky2_port *sky2)
                [FC_BOTH]       = "both",
        };
 
-       /* enable Rx/Tx */
-       reg = gma_read16(hw, port, GM_GP_CTRL);
-       reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
-       gma_write16(hw, port, GM_GP_CTRL, reg);
+       sky2_enable_rx_tx(sky2);
 
        gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
 
index 20ab161923253835b7ee760f8fc027bdcc8aa82c..737df6032bbc1d4bd9635b78210a52bcfa7efea2 100644 (file)
@@ -646,7 +646,7 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
                error = copy_from_user(data, ifr->ifr_data, sizeof(data));
                if (error) {
                        pr_err("cant copy from user\n");
-                       RET(error);
+                       RET(-EFAULT);
                }
                DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
        }
@@ -665,7 +665,7 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
                    data[2]);
                error = copy_to_user(ifr->ifr_data, data, sizeof(data));
                if (error)
-                       RET(error);
+                       RET(-EFAULT);
                break;
 
        case BDX_OP_WRITE:
index c0e70006374e826930f8797b1c1c2a65710ea78c..06b552fca63d7724b2c382fa4d2280dbaba8b0fe 100644 (file)
@@ -367,8 +367,8 @@ static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, };
 static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
 
 
-#define dr32(reg)              readl(de->regs + (reg))
-#define dw32(reg,val)          writel((val), de->regs + (reg))
+#define dr32(reg)      ioread32(de->regs + (reg))
+#define dw32(reg, val) iowrite32((val), de->regs + (reg))
 
 
 static void de_rx_err_acct (struct de_private *de, unsigned rx_tail,
@@ -1706,6 +1706,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de)
                int value, boguscnt = 100000;
                do {
                        value = dr32(ROMCmd);
+                       rmb();
                } while (value < 0 && --boguscnt > 0);
                de->dev->dev_addr[i] = value;
                udelay(1);
index 4a34833b85ddad284c1f19efff1bf9d23ed7f7e1..807470e156affad7d05529ed7ffb0d29d0973c48 100644 (file)
@@ -3215,6 +3215,8 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
                                           __func__, __LINE__, (u32) skb);
                        if (skb) {
                                skb->data = skb->head + NET_SKB_PAD;
+                               skb->len = 0;
+                               skb_reset_tail_pointer(skb);
                                __skb_queue_head(&ugeth->rx_recycle, skb);
                        }
 
index 1f802e90474c3ccd342a70fb8b7352cadedf6bcd..9516f382a6baf76dfdafe63afdd3b22380a2595f 100644 (file)
@@ -344,7 +344,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                        return 2;
                }
 
-               if (size > ETH_FRAME_LEN) {
+               if (size > dev->net->mtu + ETH_HLEN) {
                        netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
                                   size);
                        return 0;
index 0a3c41faea9c2118dd28f6c558c939002c34d135..4dd23513c5af1d661e23498740fd9f20841426e0 100644 (file)
@@ -1334,7 +1334,6 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
        /* check for port already opened, if not set the termios */
        serial->open_count++;
        if (serial->open_count == 1) {
-               tty->low_latency = 1;
                serial->rx_state = RX_IDLE;
                /* Force default termio settings */
                _hso_serial_set_termios(tty, NULL);
index 78eb3190b9b1343bee9e1cd786090c395ebd0877..1edb7a61983c05660aaec2624e596159ab2cd5c9 100644 (file)
@@ -340,7 +340,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
 
        skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len);
 
-       err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 2, skb);
+       err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 2, skb, gfp);
        if (err < 0)
                dev_kfree_skb(skb);
 
@@ -385,8 +385,8 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
 
        /* chain first in list head */
        first->private = (unsigned long)list;
-       err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
-                                      first);
+       err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
+                                   first, gfp);
        if (err < 0)
                give_pages(vi, first);
 
@@ -404,7 +404,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
 
        sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE);
 
-       err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 1, page);
+       err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 1, page, gfp);
        if (err < 0)
                give_pages(vi, page);
 
index b504bd56136210776fa0d31e87a5e00b687cb03b..d14e207de1df8c8f074d0428e0d21d380344a7f2 100644 (file)
@@ -2262,7 +2262,8 @@ start:
                vxge_debug_init(VXGE_ERR,
                        "%s: memory allocation failed",
                        VXGE_DRIVER_NAME);
-               return  -ENOMEM;
+               ret = -ENOMEM;
+               goto alloc_entries_failed;
        }
 
        vdev->vxge_entries =
@@ -2271,8 +2272,8 @@ start:
        if (!vdev->vxge_entries) {
                vxge_debug_init(VXGE_ERR, "%s: memory allocation failed",
                        VXGE_DRIVER_NAME);
-               kfree(vdev->entries);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto alloc_vxge_entries_failed;
        }
 
        for (i = 0, j = 0; i < vdev->no_of_vpath; i++) {
@@ -2303,22 +2304,32 @@ start:
                vxge_debug_init(VXGE_ERR,
                        "%s: MSI-X enable failed for %d vectors, ret: %d",
                        VXGE_DRIVER_NAME, vdev->intr_cnt, ret);
+               if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3)) {
+                       ret = -ENODEV;
+                       goto enable_msix_failed;
+               }
+
                kfree(vdev->entries);
                kfree(vdev->vxge_entries);
                vdev->entries = NULL;
                vdev->vxge_entries = NULL;
-
-               if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3))
-                       return -ENODEV;
                /* Try with less no of vector by reducing no of vpaths count */
                temp = (ret - 1)/2;
                vxge_close_vpaths(vdev, temp);
                vdev->no_of_vpath = temp;
                goto start;
-       } else if (ret < 0)
-               return -ENODEV;
-
+       } else if (ret < 0) {
+               ret = -ENODEV;
+               goto enable_msix_failed;
+       }
        return 0;
+
+enable_msix_failed:
+       kfree(vdev->vxge_entries);
+alloc_vxge_entries_failed:
+       kfree(vdev->entries);
+alloc_entries_failed:
+       return ret;
 }
 
 static int vxge_enable_msix(struct vxgedev *vdev)
index 166e77dfffda9f9ec1b00c764d09b5b41b763506..e47f5a986b1c213c7f14e43b38dda541504c8b7d 100644 (file)
@@ -37,8 +37,6 @@
 #include <net/x25device.h>
 #include "x25_asy.h"
 
-#include <net/x25device.h>
-
 static struct net_device **x25_asy_devs;
 static int x25_asy_maxdev = SL_NRUNIT;
 
index 3f283bff0ff7146447419ea714ef7cdd78884b12..11491354e5b5bf3de80d0b91ee13d7a203a0e914 100644 (file)
@@ -1192,7 +1192,7 @@ int i2400m_fw_hdr_check(struct i2400m *i2400m,
        unsigned module_type, header_len, major_version, minor_version,
                module_id, module_vendor, date, size;
 
-       module_type = bcf_hdr->module_type;
+       module_type = le32_to_cpu(bcf_hdr->module_type);
        header_len = sizeof(u32) * le32_to_cpu(bcf_hdr->header_len);
        major_version = (le32_to_cpu(bcf_hdr->header_version) & 0xffff0000)
                >> 16;
index 82ab532a492335c803af5f1cd32f34eb527a334a..a93dc18a45c3fc9e0911197f7292948518741927 100644 (file)
@@ -739,17 +739,27 @@ err_out:
 static void ar9170_usb_firmware_failed(struct ar9170_usb *aru)
 {
        struct device *parent = aru->udev->dev.parent;
+       struct usb_device *udev;
+
+       /*
+        * Store a copy of the usb_device pointer locally.
+        * This is because device_release_driver initiates
+        * ar9170_usb_disconnect, which in turn frees our
+        * driver context (aru).
+        */
+       udev = aru->udev;
 
        complete(&aru->firmware_loading_complete);
 
        /* unbind anything failed */
        if (parent)
                device_lock(parent);
-       device_release_driver(&aru->udev->dev);
+
+       device_release_driver(&udev->dev);
        if (parent)
                device_unlock(parent);
 
-       usb_put_dev(aru->udev);
+       usb_put_dev(udev);
 }
 
 static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context)
index e0c244b02f05d17cc1ee9fb7cc12dd9e0e01541e..31c008042bfe066238edc359111047d8064693d3 100644 (file)
@@ -126,6 +126,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
        ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
        ah->ah_noise_floor = -95;       /* until first NF calibration is run */
        sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
+       ah->ah_current_channel = &sc->channels[0];
 
        /*
         * Find the mac version
index cc6d41dec332091eeef2c9a0b7905f2e26c95cfe..648972df369d849fa8d2e6a1ba836953787aef63 100644 (file)
@@ -195,7 +195,7 @@ static const struct ieee80211_rate ath5k_rates[] = {
 static int __devinit   ath5k_pci_probe(struct pci_dev *pdev,
                                const struct pci_device_id *id);
 static void __devexit  ath5k_pci_remove(struct pci_dev *pdev);
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int             ath5k_pci_suspend(struct device *dev);
 static int             ath5k_pci_resume(struct device *dev);
 
@@ -203,7 +203,7 @@ static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
 #define ATH5K_PM_OPS   (&ath5k_pm_ops)
 #else
 #define ATH5K_PM_OPS   NULL
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 static struct pci_driver ath5k_pci_driver = {
        .name           = KBUILD_MODNAME,
@@ -222,7 +222,6 @@ static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
                struct ath5k_txq *txq);
 static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-static int ath5k_reset_wake(struct ath5k_softc *sc);
 static int ath5k_start(struct ieee80211_hw *hw);
 static void ath5k_stop(struct ieee80211_hw *hw);
 static int ath5k_add_interface(struct ieee80211_hw *hw,
@@ -709,7 +708,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
        ieee80211_free_hw(hw);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ath5k_pci_suspend(struct device *dev)
 {
        struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev));
@@ -735,7 +734,7 @@ static int ath5k_pci_resume(struct device *dev)
        ath5k_led_enable(sc);
        return 0;
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 
 /***********************\
@@ -2770,7 +2769,7 @@ ath5k_tasklet_reset(unsigned long data)
 {
        struct ath5k_softc *sc = (void *)data;
 
-       ath5k_reset_wake(sc);
+       ath5k_reset(sc, sc->curchan);
 }
 
 /*
@@ -2941,23 +2940,13 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
        ath5k_beacon_config(sc);
        /* intrs are enabled by ath5k_beacon_config */
 
+       ieee80211_wake_queues(sc->hw);
+
        return 0;
 err:
        return ret;
 }
 
-static int
-ath5k_reset_wake(struct ath5k_softc *sc)
-{
-       int ret;
-
-       ret = ath5k_reset(sc, sc->curchan);
-       if (!ret)
-               ieee80211_wake_queues(sc->hw);
-
-       return ret;
-}
-
 static int ath5k_start(struct ieee80211_hw *hw)
 {
        return ath5k_init(hw->priv);
@@ -3151,13 +3140,15 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
 
        if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
                if (*new_flags & FIF_PROMISC_IN_BSS) {
-                       rfilt |= AR5K_RX_FILTER_PROM;
                        __set_bit(ATH_STAT_PROMISC, sc->status);
                } else {
                        __clear_bit(ATH_STAT_PROMISC, sc->status);
                }
        }
 
+       if (test_bit(ATH_STAT_PROMISC, sc->status))
+               rfilt |= AR5K_RX_FILTER_PROM;
+
        /* Note, AR5K_RX_FILTER_MCAST is already enabled */
        if (*new_flags & FIF_ALLMULTI) {
                mfilt[0] =  ~0;
index 1b81c4778800f62222eec48bc88c61ff993e9a69..492cbb15720d2076667681a8860a7ed866a2df5f 100644 (file)
@@ -1814,6 +1814,13 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
        u8 def_ant, tx_ant, ee_mode;
        u32 sta_id1 = 0;
 
+       /* if channel is not initialized yet we can't set the antennas
+        * so just store the mode. it will be set on the next reset */
+       if (channel == NULL) {
+               ah->ah_ant_mode = ant_mode;
+               return;
+       }
+
        def_ant = ah->ah_def_ant;
 
        ATH5K_TRACE(ah->ah_sc);
index 3db19172b43b7a1aa165e68463fabaf71dd4d278..859aa4ab07698aafcd937b606cb7bafd7f4e05fe 100644 (file)
@@ -1198,7 +1198,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
                int r;
 
                ath_print(common, ATH_DBG_FATAL,
-                         "Unable to stop TxDMA. Reset HAL!\n");
+                         "Failed to stop TX DMA. Resetting hardware!\n");
 
                spin_lock_bh(&sc->sc_resetlock);
                r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false);
@@ -1728,6 +1728,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
        } else
                bf->bf_isnullfunc = false;
 
+       bf->bf_tx_aborted = false;
+
        return 0;
 }
 
@@ -1989,7 +1991,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
        int nbad = 0;
        int isaggr = 0;
 
-       if (bf->bf_tx_aborted)
+       if (bf->bf_lastbf->bf_tx_aborted)
                return 0;
 
        isaggr = bf_isaggr(bf);
index db72461c486b50a2c90a3fa09e6ce6958eb99eac..29b31a694b59cc2140cf7b044757f29c5dfd9701 100644 (file)
@@ -594,6 +594,7 @@ static int prism2_config(struct pcmcia_device *link)
        local_info_t *local;
        int ret = 1;
        struct hostap_cs_priv *hw_priv;
+       unsigned long flags;
 
        PDEBUG(DEBUG_FLOW, "prism2_config()\n");
 
@@ -625,9 +626,15 @@ static int prism2_config(struct pcmcia_device *link)
        local->hw_priv = hw_priv;
        hw_priv->link = link;
 
+       /*
+        * Make sure the IRQ handler cannot proceed until at least
+        * dev->base_addr is initialized.
+        */
+       spin_lock_irqsave(&local->irq_init_lock, flags);
+
        ret = pcmcia_request_irq(link, prism2_interrupt);
        if (ret)
-               goto failed;
+               goto failed_unlock;
 
        /*
         * This actually configures the PCMCIA socket -- setting up
@@ -636,11 +643,13 @@ static int prism2_config(struct pcmcia_device *link)
         */
        ret = pcmcia_request_configuration(link, &link->conf);
        if (ret)
-               goto failed;
+               goto failed_unlock;
 
        dev->irq = link->irq;
        dev->base_addr = link->io.BasePort1;
 
+       spin_unlock_irqrestore(&local->irq_init_lock, flags);
+
        /* Finally, report what we've done */
        printk(KERN_INFO "%s: index 0x%02x: ",
               dev_info, link->conf.ConfigIndex);
@@ -667,6 +676,8 @@ static int prism2_config(struct pcmcia_device *link)
 
        return ret;
 
+ failed_unlock:
+        spin_unlock_irqrestore(&local->irq_init_lock, flags);
  failed:
        kfree(hw_priv);
        prism2_release((u_long)link);
index d70732819423d25d09627fa0bc371be5f6976896..2f999fc94f60ca9b36bb11d70fd29096c85eaf7e 100644 (file)
@@ -2618,17 +2618,20 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
        int events = 0;
        u16 ev;
 
+       iface = netdev_priv(dev);
+       local = iface->local;
+
        /* Detect early interrupt before driver is fully configued */
+       spin_lock(&local->irq_init_lock);
        if (!dev->base_addr) {
                if (net_ratelimit()) {
                        printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
                               dev->name);
                }
+               spin_unlock(&local->irq_init_lock);
                return IRQ_HANDLED;
        }
-
-       iface = netdev_priv(dev);
-       local = iface->local;
+       spin_unlock(&local->irq_init_lock);
 
        prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
 
@@ -3147,6 +3150,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
        spin_lock_init(&local->cmdlock);
        spin_lock_init(&local->baplock);
        spin_lock_init(&local->lock);
+       spin_lock_init(&local->irq_init_lock);
        mutex_init(&local->rid_bap_mtx);
 
        if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES)
index 3d238917af07f32bcd16ffcf8eb75f90f824b120..1ba33be98b254ce9ef8a56fcb6c55501d14a9839 100644 (file)
@@ -654,7 +654,7 @@ struct local_info {
        rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock
                              * when removing entries from the list.
                              * TX and RX paths can use read lock. */
-       spinlock_t cmdlock, baplock, lock;
+       spinlock_t cmdlock, baplock, lock, irq_init_lock;
        struct mutex rid_bap_mtx;
        u16 infofid; /* MAC buffer id for info frame */
        /* txfid, intransmitfid, next_txtid, and next_alloc are protected by
index 068f7f8435c5d98c63626062a98f46f1853c6e2e..c44a303e62ed45c2bdc9ea9b77db020eb927c39c 100644 (file)
@@ -2852,6 +2852,7 @@ static struct iwl_lib_ops iwl3945_lib = {
        .isr = iwl_isr_legacy,
        .config_ap = iwl3945_config_ap,
        .manage_ibss_station = iwl3945_manage_ibss_station,
+       .recover_from_tx_stall = iwl_bg_monitor_recover,
        .check_plcp_health = iwl3945_good_plcp_health,
 
        .debugfs_ops = {
index 1004cfc403b1a3d8316243a58cd16dcc273f93ee..0f292a210ed92d1a67153234b56045647807f3f9 100644 (file)
@@ -1119,10 +1119,9 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
                                           struct iwl_scan_channel *scan_ch)
 {
        const struct ieee80211_supported_band *sband;
-       const struct iwl_channel_info *ch_info;
        u16 passive_dwell = 0;
        u16 active_dwell = 0;
-       int i, added = 0;
+       int added = 0;
        u16 channel = 0;
 
        sband = iwl_get_hw_mode(priv, band);
@@ -1137,32 +1136,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
        if (passive_dwell <= active_dwell)
                passive_dwell = active_dwell + 1;
 
-       /* only scan single channel, good enough to reset the RF */
-       /* pick the first valid not in-use channel */
-       if (band == IEEE80211_BAND_5GHZ) {
-               for (i = 14; i < priv->channel_count; i++) {
-                       if (priv->channel_info[i].channel !=
-                           le16_to_cpu(priv->staging_rxon.channel)) {
-                               channel = priv->channel_info[i].channel;
-                               ch_info = iwl_get_channel_info(priv,
-                                       band, channel);
-                               if (is_channel_valid(ch_info))
-                                       break;
-                       }
-               }
-       } else {
-               for (i = 0; i < 14; i++) {
-                       if (priv->channel_info[i].channel !=
-                           le16_to_cpu(priv->staging_rxon.channel)) {
-                                       channel =
-                                               priv->channel_info[i].channel;
-                                       ch_info = iwl_get_channel_info(priv,
-                                               band, channel);
-                                       if (is_channel_valid(ch_info))
-                                               break;
-                       }
-               }
-       }
+       channel = iwl_get_single_channel_number(priv, band);
        if (channel) {
                scan_ch->channel = cpu_to_le16(channel);
                scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
index c402bfc83f36360358ebeef3ab1fe4cbeeb863e4..7d614c4d3c6200d5410bba749105f4d371b2e5b7 100644 (file)
@@ -1125,6 +1125,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
        struct ieee80211_sta *sta;
        struct iwl_station_priv *sta_priv;
 
+       rcu_read_lock();
        sta = ieee80211_find_sta(priv->vif, hdr->addr1);
        if (sta) {
                sta_priv = (void *)sta->drv_priv;
@@ -1133,6 +1134,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
                    atomic_dec_return(&sta_priv->pending_frames) == 0)
                        ieee80211_sta_block_awake(priv->hw, sta, false);
        }
+       rcu_read_unlock();
 
        ieee80211_tx_status_irqsafe(priv->hw, skb);
 }
@@ -1297,6 +1299,11 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
        sta_id = ba_resp->sta_id;
        tid = ba_resp->tid;
        agg = &priv->stations[sta_id].tid[tid].agg;
+       if (unlikely(agg->txq_id != scd_flow)) {
+               IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n",
+                       scd_flow, agg->txq_id);
+               return;
+       }
 
        /* Find index just before block-ack window */
        index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
index aef4f71f1981c3e31461932228bbdb9f3aedf15b..24aff654fa9c44251b11f3d12ab63d639ea06384 100644 (file)
@@ -1484,6 +1484,156 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
 }
 
 
+/*****************************************************************************
+ *
+ * sysfs attributes
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+
+/*
+ * The following adds a new attribute to the sysfs representation
+ * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
+ * used for controlling the debug level.
+ *
+ * See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
+ */
+static ssize_t show_debug_level(struct device *d,
+                               struct device_attribute *attr, char *buf)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+       return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
+}
+static ssize_t store_debug_level(struct device *d,
+                               struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(buf, 0, &val);
+       if (ret)
+               IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
+       else {
+               priv->debug_level = val;
+               if (iwl_alloc_traffic_mem(priv))
+                       IWL_ERR(priv,
+                               "Not enough memory to generate traffic log\n");
+       }
+       return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
+                       show_debug_level, store_debug_level);
+
+
+#endif /* CONFIG_IWLWIFI_DEBUG */
+
+
+static ssize_t show_temperature(struct device *d,
+                               struct device_attribute *attr, char *buf)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+
+       if (!iwl_is_alive(priv))
+               return -EAGAIN;
+
+       return sprintf(buf, "%d\n", priv->temperature);
+}
+
+static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
+
+static ssize_t show_tx_power(struct device *d,
+                            struct device_attribute *attr, char *buf)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+
+       if (!iwl_is_ready_rf(priv))
+               return sprintf(buf, "off\n");
+       else
+               return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
+}
+
+static ssize_t store_tx_power(struct device *d,
+                             struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (ret)
+               IWL_INFO(priv, "%s is not in decimal form.\n", buf);
+       else {
+               ret = iwl_set_tx_power(priv, val, false);
+               if (ret)
+                       IWL_ERR(priv, "failed setting tx power (0x%d).\n",
+                               ret);
+               else
+                       ret = count;
+       }
+       return ret;
+}
+
+static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
+
+static ssize_t show_rts_ht_protection(struct device *d,
+                            struct device_attribute *attr, char *buf)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+
+       return sprintf(buf, "%s\n",
+               priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
+}
+
+static ssize_t store_rts_ht_protection(struct device *d,
+                             struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (ret)
+               IWL_INFO(priv, "Input is not in decimal form.\n");
+       else {
+               if (!iwl_is_associated(priv))
+                       priv->cfg->use_rts_for_ht = val ? true : false;
+               else
+                       IWL_ERR(priv, "Sta associated with AP - "
+                               "Change protection mechanism is not allowed\n");
+               ret = count;
+       }
+       return ret;
+}
+
+static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
+                       show_rts_ht_protection, store_rts_ht_protection);
+
+
+static struct attribute *iwl_sysfs_entries[] = {
+       &dev_attr_temperature.attr,
+       &dev_attr_tx_power.attr,
+       &dev_attr_rts_ht_protection.attr,
+#ifdef CONFIG_IWLWIFI_DEBUG
+       &dev_attr_debug_level.attr,
+#endif
+       NULL
+};
+
+static struct attribute_group iwl_attribute_group = {
+       .name = NULL,           /* put in device directory */
+       .attrs = iwl_sysfs_entries,
+};
+
 /******************************************************************************
  *
  * uCode download functions
@@ -1965,6 +2115,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        if (err)
                IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
+       err = sysfs_create_group(&priv->pci_dev->dev.kobj,
+                                       &iwl_attribute_group);
+       if (err) {
+               IWL_ERR(priv, "failed to create sysfs device attributes\n");
+               goto out_unbind;
+       }
+
        /* We have our copies now, allow OS release its copies */
        release_firmware(ucode_raw);
        complete(&priv->_agn.firmware_loading_complete);
@@ -3234,10 +3391,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
        int ret;
        u8 sta_id;
 
-       sta_priv->common.sta_id = IWL_INVALID_STATION;
-
        IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
                        sta->addr);
+       mutex_lock(&priv->mutex);
+       IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+                       sta->addr);
+       sta_priv->common.sta_id = IWL_INVALID_STATION;
 
        atomic_set(&sta_priv->pending_frames, 0);
        if (vif->type == NL80211_IFTYPE_AP)
@@ -3249,6 +3408,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
                IWL_ERR(priv, "Unable to add station %pM (%d)\n",
                        sta->addr, ret);
                /* Should we return success if return code is EEXIST ? */
+               mutex_unlock(&priv->mutex);
                return ret;
        }
 
@@ -3258,145 +3418,11 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
        IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
                       sta->addr);
        iwl_rs_rate_init(priv, sta, sta_id);
+       mutex_unlock(&priv->mutex);
 
        return 0;
 }
 
-/*****************************************************************************
- *
- * sysfs attributes
- *
- *****************************************************************************/
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-
-/*
- * The following adds a new attribute to the sysfs representation
- * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
- * used for controlling the debug level.
- *
- * See the level definitions in iwl for details.
- *
- * The debug_level being managed using sysfs below is a per device debug
- * level that is used instead of the global debug level if it (the per
- * device debug level) is set.
- */
-static ssize_t show_debug_level(struct device *d,
-                               struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
-}
-static ssize_t store_debug_level(struct device *d,
-                               struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 0, &val);
-       if (ret)
-               IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
-       else {
-               priv->debug_level = val;
-               if (iwl_alloc_traffic_mem(priv))
-                       IWL_ERR(priv,
-                               "Not enough memory to generate traffic log\n");
-       }
-       return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
-                       show_debug_level, store_debug_level);
-
-
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
-
-static ssize_t show_temperature(struct device *d,
-                               struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       if (!iwl_is_alive(priv))
-               return -EAGAIN;
-
-       return sprintf(buf, "%d\n", priv->temperature);
-}
-
-static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
-
-static ssize_t show_tx_power(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       if (!iwl_is_ready_rf(priv))
-               return sprintf(buf, "off\n");
-       else
-               return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
-}
-
-static ssize_t store_tx_power(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 10, &val);
-       if (ret)
-               IWL_INFO(priv, "%s is not in decimal form.\n", buf);
-       else {
-               ret = iwl_set_tx_power(priv, val, false);
-               if (ret)
-                       IWL_ERR(priv, "failed setting tx power (0x%d).\n",
-                               ret);
-               else
-                       ret = count;
-       }
-       return ret;
-}
-
-static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
-
-static ssize_t show_rts_ht_protection(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       return sprintf(buf, "%s\n",
-               priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
-}
-
-static ssize_t store_rts_ht_protection(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 10, &val);
-       if (ret)
-               IWL_INFO(priv, "Input is not in decimal form.\n");
-       else {
-               if (!iwl_is_associated(priv))
-                       priv->cfg->use_rts_for_ht = val ? true : false;
-               else
-                       IWL_ERR(priv, "Sta associated with AP - "
-                               "Change protection mechanism is not allowed\n");
-               ret = count;
-       }
-       return ret;
-}
-
-static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
-                       show_rts_ht_protection, store_rts_ht_protection);
-
-
 /*****************************************************************************
  *
  * driver setup and teardown
@@ -3550,21 +3576,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
        kfree(priv->scan_cmd);
 }
 
-static struct attribute *iwl_sysfs_entries[] = {
-       &dev_attr_temperature.attr,
-       &dev_attr_tx_power.attr,
-       &dev_attr_rts_ht_protection.attr,
-#ifdef CONFIG_IWLWIFI_DEBUG
-       &dev_attr_debug_level.attr,
-#endif
-       NULL
-};
-
-static struct attribute_group iwl_attribute_group = {
-       .name = NULL,           /* put in device directory */
-       .attrs = iwl_sysfs_entries,
-};
-
 static struct ieee80211_ops iwl_hw_ops = {
        .tx = iwl_mac_tx,
        .start = iwl_mac_start,
@@ -3750,11 +3761,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
                goto out_disable_msi;
        }
-       err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
-       if (err) {
-               IWL_ERR(priv, "failed to create sysfs device attributes\n");
-               goto out_free_irq;
-       }
 
        iwl_setup_deferred_work(priv);
        iwl_setup_rx_handlers(priv);
@@ -3788,15 +3794,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        err = iwl_request_firmware(priv, true);
        if (err)
-               goto out_remove_sysfs;
+               goto out_destroy_workqueue;
 
        return 0;
 
- out_remove_sysfs:
+ out_destroy_workqueue:
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
-       sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
- out_free_irq:
        free_irq(priv->pci_dev->irq, priv);
        iwl_free_isr_ict(priv);
  out_disable_msi:
index 5a7eca8fb789621f69d15a6b79e5bae143386664..426e95567de388619dc120fe08178cab038667d9 100644 (file)
@@ -854,6 +854,45 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
 }
 EXPORT_SYMBOL(iwl_set_rxon_chain);
 
+/* Return valid channel */
+u8 iwl_get_single_channel_number(struct iwl_priv *priv,
+                                 enum ieee80211_band band)
+{
+       const struct iwl_channel_info *ch_info;
+       int i;
+       u8 channel = 0;
+
+       /* only scan single channel, good enough to reset the RF */
+       /* pick the first valid not in-use channel */
+       if (band == IEEE80211_BAND_5GHZ) {
+               for (i = 14; i < priv->channel_count; i++) {
+                       if (priv->channel_info[i].channel !=
+                           le16_to_cpu(priv->staging_rxon.channel)) {
+                               channel = priv->channel_info[i].channel;
+                               ch_info = iwl_get_channel_info(priv,
+                                       band, channel);
+                               if (is_channel_valid(ch_info))
+                                       break;
+                       }
+               }
+       } else {
+               for (i = 0; i < 14; i++) {
+                       if (priv->channel_info[i].channel !=
+                           le16_to_cpu(priv->staging_rxon.channel)) {
+                                       channel =
+                                               priv->channel_info[i].channel;
+                                       ch_info = iwl_get_channel_info(priv,
+                                               band, channel);
+                                       if (is_channel_valid(ch_info))
+                                               break;
+                       }
+               }
+       }
+
+       return channel;
+}
+EXPORT_SYMBOL(iwl_get_single_channel_number);
+
 /**
  * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
  * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
index 7e5a5ba41fd210e492655a5248d39bd7d4c7beb1..31775bd9c36170faa839da119456fd4cf747a385 100644 (file)
@@ -343,6 +343,8 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv);
 int iwl_full_rxon_required(struct iwl_priv *priv);
 void iwl_set_rxon_chain(struct iwl_priv *priv);
 int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
+u8 iwl_get_single_channel_number(struct iwl_priv *priv,
+                                 enum ieee80211_band band);
 void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
 u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
                         struct ieee80211_sta_ht_cap *sta_ht_inf);
index 5d3f51ff2f0d075ad6ef81c022a687651afd2e07..386c5f96eff81c6467f026bc970c39734b853ffb 100644 (file)
@@ -491,6 +491,7 @@ void iwl_bg_abort_scan(struct work_struct *work)
 
        mutex_lock(&priv->mutex);
 
+       cancel_delayed_work_sync(&priv->scan_check);
        set_bit(STATUS_SCAN_ABORTING, &priv->status);
        iwl_send_scan_abort(priv);
 
index 83a26361a9b56b35d4364c93b9f9df32905c8cc6..c27c13fbb1aec26bac302623b96d089e1f13c0dd 100644 (file)
@@ -1373,10 +1373,14 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
 
        IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
                        sta->addr);
+       mutex_lock(&priv->mutex);
+       IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
+                       sta->addr);
        ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
        if (ret)
                IWL_ERR(priv, "Error removing station %pM\n",
                        sta->addr);
+       mutex_unlock(&priv->mutex);
        return ret;
 }
 EXPORT_SYMBOL(iwl_mac_sta_remove);
index 3e5bffb6034f47bad2d69ed89b7b38ae0f25be30..a27872de41061d62cec0af818aa72f88927396da 100644 (file)
@@ -1844,6 +1844,49 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 #endif
 }
 
+static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
+                                              struct ieee80211_vif *vif,
+                                              enum ieee80211_band band,
+                                              struct iwl3945_scan_channel *scan_ch)
+{
+       const struct ieee80211_supported_band *sband;
+       u16 passive_dwell = 0;
+       u16 active_dwell = 0;
+       int added = 0;
+       u8 channel = 0;
+
+       sband = iwl_get_hw_mode(priv, band);
+       if (!sband) {
+               IWL_ERR(priv, "invalid band\n");
+               return added;
+       }
+
+       active_dwell = iwl_get_active_dwell_time(priv, band, 0);
+       passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
+
+       if (passive_dwell <= active_dwell)
+               passive_dwell = active_dwell + 1;
+
+
+       channel = iwl_get_single_channel_number(priv, band);
+
+       if (channel) {
+               scan_ch->channel = channel;
+               scan_ch->type = 0;      /* passive */
+               scan_ch->active_dwell = cpu_to_le16(active_dwell);
+               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+               /* Set txpower levels to defaults */
+               scan_ch->tpc.dsp_atten = 110;
+               if (band == IEEE80211_BAND_5GHZ)
+                       scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+               else
+                       scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+               added++;
+       } else
+               IWL_ERR(priv, "no valid channel found\n");
+       return added;
+}
+
 static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
                                         enum ieee80211_band band,
                                     u8 is_active, u8 n_probes,
@@ -2992,9 +3035,16 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        /* select Rx antennas */
        scan->flags |= iwl3945_get_antenna_flags(priv);
 
-       scan->channel_count =
-               iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
-                       (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
+       if (priv->is_internal_short_scan) {
+               scan->channel_count =
+                       iwl3945_get_single_channel_for_scan(priv, vif, band,
+                               (void *)&scan->data[le16_to_cpu(
+                               scan->tx_cmd.len)]);
+       } else {
+               scan->channel_count =
+                       iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
+                               (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
+       }
 
        if (scan->channel_count == 0) {
                IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
@@ -3387,10 +3437,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
        bool is_ap = vif->type == NL80211_IFTYPE_STATION;
        u8 sta_id;
 
-       sta_priv->common.sta_id = IWL_INVALID_STATION;
-
        IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
                        sta->addr);
+       mutex_lock(&priv->mutex);
+       IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+                       sta->addr);
+       sta_priv->common.sta_id = IWL_INVALID_STATION;
+
 
        ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
                                     &sta_id);
@@ -3398,6 +3451,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
                IWL_ERR(priv, "Unable to add station %pM (%d)\n",
                        sta->addr, ret);
                /* Should we return success if return code is EEXIST ? */
+               mutex_unlock(&priv->mutex);
                return ret;
        }
 
@@ -3407,6 +3461,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
        IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
                       sta->addr);
        iwl3945_rs_rate_init(priv, sta, sta_id);
+       mutex_unlock(&priv->mutex);
 
        return 0;
 }
index a115bfa9513a8776f49139924e475a517884819c..7a377f5b76627540b6309f563bf6c974be503799 100644 (file)
@@ -329,9 +329,8 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
        /* create the exported radio header */
 
        /* radiotap header */
-       radiotap_hdr.hdr.it_version = 0;
-       /* XXX must check this value for pad */
-       radiotap_hdr.hdr.it_pad = 0;
+       memset(&radiotap_hdr, 0, sizeof(radiotap_hdr));
+       /* XXX must check radiotap_hdr.hdr.it_pad for pad */
        radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
        radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
        radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
index 6a04c2157f73f3788109afcdfbc50c4ecdf62b9e..817fffc0de4b5093c869fc11a5f72aa9ca0ab3ba 100644 (file)
@@ -549,7 +549,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
 
        prxpd = (struct rxpd *) skb->data;
 
-       stats.flag = 0;
+       memset(&stats, 0, sizeof(stats));
        if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
                stats.flag |= RX_FLAG_FAILED_FCS_CRC;
        stats.freq = priv->cur_freq;
index 9bcee10c9308f861089843ccfe7c9b3009907e6d..4a0a0e5265c9bc068ee7116a240b5f8fa7560487 100644 (file)
@@ -239,8 +239,11 @@ static struct of_device_id airport_match[] =
 MODULE_DEVICE_TABLE(of, airport_match);
 
 static struct macio_driver airport_driver = {
-       .name           = DRIVER_NAME,
-       .match_table    = airport_match,
+       .driver = {
+               .name           = DRIVER_NAME,
+               .owner          = THIS_MODULE,
+               .of_match_table = airport_match,
+       },
        .probe          = airport_attach,
        .remove         = airport_detach,
        .suspend        = airport_suspend,
index 07c4528f6e6b895d59e2cddc3fd30edcf80cb000..a5ea89cde8c43a9c837018459e9f689a83162e1e 100644 (file)
@@ -41,6 +41,8 @@ static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
        { PCI_DEVICE(0x1260, 0x3877) },
        /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
        { PCI_DEVICE(0x1260, 0x3886) },
+       /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */
+       { PCI_DEVICE(0x1260, 0xffff) },
        { },
 };
 
index d5b197b4d5bb492ac70c8e2a98297a2e82e5e356..73073259f50814b36ab947e4fd58fc6293e6f459 100644 (file)
@@ -80,6 +80,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
        {USB_DEVICE(0x1413, 0x5400)},   /* Telsey 802.11g USB2.0 Adapter */
        {USB_DEVICE(0x1435, 0x0427)},   /* Inventel UR054G */
        {USB_DEVICE(0x2001, 0x3704)},   /* DLink DWL-G122 rev A2 */
+       {USB_DEVICE(0x413c, 0x5513)},   /* Dell WLA3310 USB Wireless Adapter */
        {USB_DEVICE(0x413c, 0x8102)},   /* Spinnaker DUT */
        {USB_DEVICE(0x413c, 0x8104)},   /* Cohiba Proto board */
        {}
index 699161327d656feb56cb7c74d081e17e277a9394..0f8b84b7224cace0167ebe5b0065da28af08986c 100644 (file)
@@ -413,7 +413,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
         */
        rt2x00_desc_read(txi, 0, &word);
        rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
-                          skb->len - TXINFO_DESC_SIZE);
+                          skb->len + TXWI_DESC_SIZE);
        rt2x00_set_field32(&word, TXINFO_W0_WIV,
                           !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
        rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
index d234285c2c81186fc096044dcfa309236e7e2d51..c561332e70092b18280fff1843f948b13603289a 100644 (file)
@@ -259,6 +259,7 @@ disable:
        sdio_disable_func(func);
 release:
        sdio_release_host(func);
+       wl1251_free_hw(wl);
        return ret;
 }
 
index b3e5580c837b782ed3cf86108b82ee3e4c5473e6..4952c3b9379dcddcbb8f2c7b1f340009f0cba15c 100644 (file)
@@ -828,7 +828,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        pci_name(pdev), err);
                return err;
        }
+
        bus = pdev->subordinate;
+       if (!bus) {
+               dev_notice(&pdev->dev, "the device is not a bridge, "
+                               "skipping\n");
+               rc = -ENODEV;
+               goto err_disable_device;
+       }
 
        /* Need to read VID early b/c it's used to differentiate CPQ and INTC
         * discovery
index 796828fce34cb5b918a485de903d3af18971ed38..c9171be74564b684ba41108fd15a566187910023 100644 (file)
@@ -340,7 +340,7 @@ int dmar_disabled = 0;
 int dmar_disabled = 1;
 #endif /*CONFIG_DMAR_DEFAULT_ON*/
 
-static int __initdata dmar_map_gfx = 1;
+static int dmar_map_gfx = 1;
 static int dmar_forcedac;
 static int intel_iommu_strict;
 
@@ -1874,14 +1874,15 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
                        }
                }
                if (found) {
+                       spin_unlock_irqrestore(&device_domain_lock, flags);
                        free_devinfo_mem(info);
                        domain_exit(domain);
                        domain = found;
                } else {
                        list_add(&info->link, &domain->devices);
                        list_add(&info->global, &device_domain_list);
+                       spin_unlock_irqrestore(&device_domain_lock, flags);
                }
-               spin_unlock_irqrestore(&device_domain_lock, flags);
        }
 
 found_domain:
@@ -3603,7 +3604,8 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
                pte = dmar_domain->pgd;
                if (dma_pte_present(pte)) {
                        free_pgtable_page(dmar_domain->pgd);
-                       dmar_domain->pgd = (struct dma_pte *)dma_pte_addr(pte);
+                       dmar_domain->pgd = (struct dma_pte *)
+                               phys_to_virt(dma_pte_addr(pte));
                }
                dmar_domain->agaw--;
        }
@@ -3719,6 +3721,12 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
         */
        printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
        rwbf_quirk = 1;
+
+       /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */
+       if (dev->revision == 0x07) {
+               printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
+               dmar_map_gfx = 0;
+       }
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
index afd2fbf7d797185f9e645ff85f7450edc7039889..c9957f68ac9bd574964271b363012aa62c8c8bc3 100644 (file)
@@ -1035,39 +1035,6 @@ error:
        return retval;
 }
 
-static void pci_remove_slot_links(struct pci_dev *dev)
-{
-       char func[10];
-       struct pci_slot *slot;
-
-       sysfs_remove_link(&dev->dev.kobj, "slot");
-       list_for_each_entry(slot, &dev->bus->slots, list) {
-               if (slot->number != PCI_SLOT(dev->devfn))
-                       continue;
-               snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
-               sysfs_remove_link(&slot->kobj, func);
-       }
-}
-
-static int pci_create_slot_links(struct pci_dev *dev)
-{
-       int result = 0;
-       char func[10];
-       struct pci_slot *slot;
-
-       list_for_each_entry(slot, &dev->bus->slots, list) {
-               if (slot->number != PCI_SLOT(dev->devfn))
-                       continue;
-               result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
-               if (result)
-                       goto out;
-               snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
-               result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
-       }
-out:
-       return result;
-}
-
 int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
        int retval;
@@ -1130,8 +1097,6 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
        if (retval)
                goto err_vga_file;
 
-       pci_create_slot_links(pdev);
-
        return 0;
 
 err_vga_file:
@@ -1181,8 +1146,6 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
        if (!sysfs_initialized)
                return;
 
-       pci_remove_slot_links(pdev);
-
        pci_remove_capabilities_sysfs(pdev);
 
        if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
index 60f30e7f1c8c1c81d874204103b58443d63c3416..740fb4ea966952e98f1b131552ee89945bffe75a 100644 (file)
@@ -2292,6 +2292,7 @@ void pci_msi_off(struct pci_dev *dev)
                pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
        }
 }
+EXPORT_SYMBOL_GPL(pci_msi_off);
 
 #ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE
 int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
index aac285a16b62bec0f84690c5241c4ee82185e383..d672a0a638162328a22027005c0b2309d5c00370 100644 (file)
@@ -34,7 +34,7 @@
  * being registered.  Consequently, the interrupt-based PCIe PME signaling will
  * not be used by any PCIe root ports in that case.
  */
-static bool pcie_pme_disabled;
+static bool pcie_pme_disabled = true;
 
 /*
  * The PCI Express Base Specification 2.0, Section 6.1.8, states the following:
@@ -64,12 +64,19 @@ bool pcie_pme_msi_disabled;
 
 static int __init pcie_pme_setup(char *str)
 {
-       if (!strcmp(str, "off"))
-               pcie_pme_disabled = true;
-       else if (!strcmp(str, "force"))
+       if (!strncmp(str, "auto", 4))
+               pcie_pme_disabled = false;
+       else if (!strncmp(str, "force", 5))
                pcie_pme_force_enable = true;
-       else if (!strcmp(str, "nomsi"))
-               pcie_pme_msi_disabled = true;
+
+       str = strchr(str, ',');
+       if (str) {
+               str++;
+               str += strspn(str, " \t");
+               if (*str && !strcmp(str, "nomsi"))
+                       pcie_pme_msi_disabled = true;
+       }
+
        return 1;
 }
 __setup("pcie_pme=", pcie_pme_setup);
index b7512cf08c58ea665c2b4afce6aaac7ca9ddf13a..477345d416417c58662ea8386a0841ba65d0dd72 100644 (file)
@@ -1457,7 +1457,8 @@ static void quirk_jmicron_ata(struct pci_dev *pdev)
        conf5 &= ~(1 << 24);  /* Clear bit 24 */
 
        switch (pdev->device) {
-       case PCI_DEVICE_ID_JMICRON_JMB360:
+       case PCI_DEVICE_ID_JMICRON_JMB360: /* SATA single port */
+       case PCI_DEVICE_ID_JMICRON_JMB362: /* SATA dual ports */
                /* The controller should be in single function ahci mode */
                conf1 |= 0x0002A100; /* Set 8, 13, 15, 17 */
                break;
@@ -1493,12 +1494,14 @@ static void quirk_jmicron_ata(struct pci_dev *pdev)
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB362, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB362, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);
index 17bed18d24ad10eb021e7d3148f8456ff5fe2277..92379e2d37e77ed4797dba23b7402f795dec80e2 100644 (file)
@@ -97,16 +97,16 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
 
        root = pci_find_parent_resource(dev, res);
        if (!root) {
-               dev_err(&dev->dev, "no compatible bridge window for %pR\n",
-                       res);
+               dev_info(&dev->dev, "no compatible bridge window for %pR\n",
+                        res);
                return -EINVAL;
        }
 
        conflict = request_resource_conflict(root, res);
        if (conflict) {
-               dev_err(&dev->dev,
-                       "address space collision: %pR conflicts with %s %pR\n",
-                       res, conflict->name, conflict);
+               dev_info(&dev->dev,
+                        "address space collision: %pR conflicts with %s %pR\n",
+                        res, conflict->name, conflict);
                return -EBUSY;
        }
 
index e0189cf7c5587ac2d182e7e55a20892c272631b4..659eaa0fc48facf81dad9c0b5c430498e01398e3 100644 (file)
@@ -97,50 +97,6 @@ static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf)
        return bus_speed_read(slot->bus->cur_bus_speed, buf);
 }
 
-static void remove_sysfs_files(struct pci_slot *slot)
-{
-       char func[10];
-       struct list_head *tmp;
-
-       list_for_each(tmp, &slot->bus->devices) {
-               struct pci_dev *dev = pci_dev_b(tmp);
-               if (PCI_SLOT(dev->devfn) != slot->number)
-                       continue;
-               sysfs_remove_link(&dev->dev.kobj, "slot");
-
-               snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
-               sysfs_remove_link(&slot->kobj, func);
-       }
-}
-
-static int create_sysfs_files(struct pci_slot *slot)
-{
-       int result;
-       char func[10];
-       struct list_head *tmp;
-
-       list_for_each(tmp, &slot->bus->devices) {
-               struct pci_dev *dev = pci_dev_b(tmp);
-               if (PCI_SLOT(dev->devfn) != slot->number)
-                       continue;
-
-               result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
-               if (result)
-                       goto fail;
-
-               snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
-               result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
-               if (result)
-                       goto fail;
-       }
-
-       return 0;
-
-fail:
-       remove_sysfs_files(slot);
-       return result;
-}
-
 static void pci_slot_release(struct kobject *kobj)
 {
        struct pci_dev *dev;
@@ -153,8 +109,6 @@ static void pci_slot_release(struct kobject *kobj)
                if (PCI_SLOT(dev->devfn) == slot->number)
                        dev->slot = NULL;
 
-       remove_sysfs_files(slot);
-
        list_del(&slot->list);
 
        kfree(slot);
@@ -346,8 +300,6 @@ placeholder:
        INIT_LIST_HEAD(&slot->list);
        list_add(&slot->list, &parent->slots);
 
-       create_sysfs_files(slot);
-
        list_for_each_entry(dev, &parent->devices, bus_list)
                if (PCI_SLOT(dev->devfn) == slot_nr)
                        dev->slot = slot;
index 7ef7adee5e4f1c2f22b6ff27658950d3139dd0d0..9fc3398455388d04159ca1f43ac2524d3c143c01 100644 (file)
@@ -671,6 +671,7 @@ static void pcmcia_requery(struct pcmcia_socket *s)
                if (old_funcs != new_funcs) {
                        /* we need to re-start */
                        pcmcia_card_remove(s, NULL);
+                       s->functions = 0;
                        pcmcia_card_add(s);
                }
        }
index 1a648b90b634890512ffb95560c1944d5d7a214a..25e5e30a18afdd6bafaae72e1c06314f42c9efb0 100644 (file)
@@ -1157,7 +1157,7 @@ static int __init m8xx_probe(struct of_device *ofdev,
        unsigned int i, m, hwirq;
        pcmconf8xx_t *pcmcia;
        int status;
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
 
        pcmcia_info("%s\n", version);
 
@@ -1301,7 +1301,7 @@ static struct of_platform_driver m8xx_pcmcia_driver = {
        .driver = {
                .name = driver_name,
                .owner = THIS_MODULE,
-               .match_table = m8xx_pcmcia_match,
+               .of_match_table = m8xx_pcmcia_match,
        },
        .probe = m8xx_probe,
        .remove = m8xx_remove,
index 424e576f3acba7a2b7c626f52e48e7454125fc00..f1d41374eea7a32426e8acfeadc903b1901bee22 100644 (file)
@@ -880,6 +880,12 @@ static struct cardbus_type cardbus_type[] = {
                .restore_state  = ti_restore_state,
                .sock_init      = ti_init,
        },
+       [CARDBUS_TYPE_ENE]      = {
+               .override       = ene_override,
+               .save_state     = ti_save_state,
+               .restore_state  = ti_restore_state,
+               .sock_init      = ti_init,
+       },
 #endif
 #ifdef CONFIG_YENTA_RICOH
        [CARDBUS_TYPE_RICOH]    = {
@@ -902,14 +908,6 @@ static struct cardbus_type cardbus_type[] = {
                .restore_state  = o2micro_restore_state,
        },
 #endif
-#ifdef CONFIG_YENTA_TI
-       [CARDBUS_TYPE_ENE]      = {
-               .override       = ene_override,
-               .save_state     = ti_save_state,
-               .restore_state  = ti_restore_state,
-               .sock_init      = ti_init,
-       },
-#endif
 };
 
 
@@ -975,7 +973,7 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id)
 /* probes the PCI interrupt, use only on override functions */
 static int yenta_probe_cb_irq(struct yenta_socket *socket)
 {
-       u8 reg;
+       u8 reg = 0;
 
        if (!socket->cb_irq)
                return -1;
@@ -989,7 +987,8 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
        }
 
        /* generate interrupt, wait */
-       reg = exca_readb(socket, I365_CSCINT);
+       if (!socket->dev->irq)
+               reg = exca_readb(socket, I365_CSCINT);
        exca_writeb(socket, I365_CSCINT, reg | I365_CSC_STSCHG);
        cb_writel(socket, CB_SOCKET_EVENT, -1);
        cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
index 576c3ed924356d5fc1f3915bce9670b498a636ca..40658e3385b45346ddc91132816e28ccfee4dd84 100644 (file)
@@ -524,7 +524,7 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
        for (i = 0; i < inlen; i++)
                ipc_data_writel(*in++, 4 * i);
 
-       ipc_command(cmd << 12 | sub);
+       ipc_command((cmd << 12) | sub | (inlen << 18));
        err = busy_loop();
 
        for (i = 0; i < outlen; i++)
index f3e22c9fe20a538581a70fc0d0134bf78a5a1b33..2f2f9a6f54fad6d75dc692fbee4d128b7ba642a4 100644 (file)
@@ -225,7 +225,6 @@ static int __devinit max17040_probe(struct i2c_client *client,
        ret = power_supply_register(&client->dev, &chip->battery);
        if (ret) {
                dev_err(&client->dev, "failed: power supply register\n");
-               i2c_set_clientdata(client, NULL);
                kfree(chip);
                return ret;
        }
@@ -245,7 +244,6 @@ static int __devexit max17040_remove(struct i2c_client *client)
 
        power_supply_unregister(&chip->battery);
        cancel_delayed_work(&chip->work);
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return 0;
 }
index 671a7d1f1f0e33e5f9f0fd4e016b742a870da3a4..8ae3732eb24bcd28e414049b583d3644fa8ffd17 100644 (file)
@@ -519,8 +519,6 @@ static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
        struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
        int i;
 
-       i2c_set_clientdata(i2c, NULL);
-
        for (i = 0; i < lp3971->num_regulators; i++)
                regulator_unregister(lp3971->rdev[i]);
 
index b3c1afc16889434f47c9fd74e387da39bb255737..2b54d9d75f11e2893ead65a3624199fa13fb9b24 100644 (file)
@@ -244,7 +244,6 @@ static int __devexit max1586_pmic_remove(struct i2c_client *client)
        for (i = 0; i <= MAX1586_V6; i++)
                if (rdev[i])
                        regulator_unregister(rdev[i]);
-       i2c_set_clientdata(client, NULL);
        kfree(rdev);
 
        return 0;
index bfc4c5ffdc966f3ab03081259faf52adce239906..4520ace3f7e707f82ccbf0fb068df921dfc6c2df 100644 (file)
@@ -357,7 +357,6 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
        dev_info(info->dev, "Max8649 regulator device is detected.\n");
        return 0;
 out:
-       i2c_set_clientdata(client, NULL);
        kfree(info);
        return ret;
 }
@@ -369,7 +368,6 @@ static int __devexit max8649_regulator_remove(struct i2c_client *client)
        if (info) {
                if (info->regulator)
                        regulator_unregister(info->regulator);
-               i2c_set_clientdata(client, NULL);
                kfree(info);
        }
 
index 3790b21879ff2f8d2c5b8000fe216f1f0770a436..d97220efae5ab4f1fde54cd909c724a3f5bf3523 100644 (file)
@@ -471,7 +471,6 @@ static int __devexit max8660_remove(struct i2c_client *client)
        for (i = 0; i < MAX8660_V_END; i++)
                if (rdev[i])
                        regulator_unregister(rdev[i]);
-       i2c_set_clientdata(client, NULL);
        kfree(rdev);
 
        return 0;
index 8e2f2098b00562fd2e9608494569f28f9b85a83f..f50afc9f287a80f04513bcf670839fcf84ebc23b 100644 (file)
@@ -538,9 +538,6 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
        struct tps_pmic *tps = i2c_get_clientdata(client);
        int i;
 
-       /* clear the client data in i2c */
-       i2c_set_clientdata(client, NULL);
-
        for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
                regulator_unregister(tps->rdev[i]);
 
index 92a8f6cacda978cfbe83a42f384bc96f7a899f63..34647fc1ee98231dc7444a2ec8d4514d2c07ded1 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/bcd.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/slab.h>
 
 /*
  * The DaVinci RTC is a simple RTC with the following
index de033b7ac21f68e67b423d711d998c06604fd90f..d827ce570a8c8eba9fee216f66a3bb3e1e184232 100644 (file)
@@ -777,7 +777,7 @@ static int __devinit ds1307_probe(struct i2c_client *client,
 
 read_rtc:
        /* read RTC registers */
-       tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf);
+       tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf);
        if (tmp != 8) {
                pr_debug("read error %d\n", tmp);
                err = -EIO;
@@ -862,7 +862,7 @@ read_rtc:
                if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
                        tmp += 12;
                i2c_smbus_write_byte_data(client,
-                               DS1307_REG_HOUR,
+                               ds1307->offset + DS1307_REG_HOUR,
                                bin2bcd(tmp));
        }
 
index 61945734ad003c379fde6424c708942b1afbbf8a..1f0007fd44314c5b65ffc39fde6df81cc568d492 100644 (file)
@@ -403,7 +403,6 @@ out_irq:
                free_irq(client->irq, client);
 
 out_free:
-       i2c_set_clientdata(client, NULL);
        kfree(ds1374);
        return ret;
 }
@@ -422,7 +421,6 @@ static int __devexit ds1374_remove(struct i2c_client *client)
        }
 
        rtc_device_unregister(ds1374->rtc);
-       i2c_set_clientdata(client, NULL);
        kfree(ds1374);
        return 0;
 }
index f0dbf9cb8f9c42f30e51b6db7dba823d887c6f61..db5d8c416d26a18e6fdb141c3bfa1d7c106e18d9 100644 (file)
@@ -279,7 +279,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op,
        if (!rtc)
                return -ENOMEM;
 
-       rtc->regs = of_iomap(op->node, 0);
+       rtc->regs = of_iomap(op->dev.of_node, 0);
        if (!rtc->regs) {
                dev_err(&op->dev, "%s: couldn't map io space\n", __func__);
                err = -ENOSYS;
@@ -290,7 +290,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op,
 
        dev_set_drvdata(&op->dev, rtc);
 
-       rtc->irq = irq_of_parse_and_map(op->node, 1);
+       rtc->irq = irq_of_parse_and_map(op->dev.of_node, 1);
        err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED,
                                                "mpc5121-rtc", &op->dev);
        if (err) {
@@ -299,7 +299,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op,
                goto out_dispose;
        }
 
-       rtc->irq_periodic = irq_of_parse_and_map(op->node, 0);
+       rtc->irq_periodic = irq_of_parse_and_map(op->dev.of_node, 0);
        err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd,
                                IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev);
        if (err) {
@@ -365,9 +365,11 @@ static struct of_device_id mpc5121_rtc_match[] __devinitdata = {
 };
 
 static struct of_platform_driver mpc5121_rtc_driver = {
-       .owner = THIS_MODULE,
-       .name = "mpc5121-rtc",
-       .match_table = mpc5121_rtc_match,
+       .driver = {
+               .name = "mpc5121-rtc",
+               .owner = THIS_MODULE,
+               .of_match_table = mpc5121_rtc_match,
+       },
        .probe = mpc5121_rtc_probe,
        .remove = __devexit_p(mpc5121_rtc_remove),
 };
index b65c82f792d9cd6f86614304db1f4c9d99077c6b..789f62f9b47d4b288ba8dffe30adeaf123c1fc84 100644 (file)
@@ -632,7 +632,6 @@ errout_reg:
        rtc_device_unregister(rx8025->rtc);
 
 errout_free:
-       i2c_set_clientdata(client, NULL);
        kfree(rx8025);
 
 errout:
@@ -656,7 +655,6 @@ static int __devexit rx8025_remove(struct i2c_client *client)
 
        rx8025_sysfs_unregister(&client->dev);
        rtc_device_unregister(rx8025->rtc);
-       i2c_set_clientdata(client, NULL);
        kfree(rx8025);
        return 0;
 }
index def4d396d0b096cef968a5572f2b5122d92eeb33..f789e002c9b013664a2588ea342b25a52acf8a1c 100644 (file)
@@ -275,7 +275,6 @@ exit_dummy:
                if (s35390a->client[i])
                        i2c_unregister_device(s35390a->client[i]);
        kfree(s35390a);
-       i2c_set_clientdata(client, NULL);
 
 exit:
        return err;
@@ -292,7 +291,6 @@ static int s35390a_remove(struct i2c_client *client)
 
        rtc_device_unregister(s35390a->rtc);
        kfree(s35390a);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index e5972b2c17b7be04be983a4460ca5aec5c7063d2..70b68d35f9694c804272c1bca502253f15a563c9 100644 (file)
@@ -495,8 +495,6 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
        pr_debug("s3c2410_rtc: RTCCON=%02x\n",
                 readb(s3c_rtc_base + S3C2410_RTCCON));
 
-       s3c_rtc_setfreq(&pdev->dev, 1);
-
        device_init_wakeup(&pdev->dev, 1);
 
        /* register RTC and exit */
@@ -510,14 +508,17 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
                goto err_nortc;
        }
 
+       s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
+
        if (s3c_rtc_cpu_type == TYPE_S3C64XX)
                rtc->max_user_freq = 32768;
        else
                rtc->max_user_freq = 128;
 
-       s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
-
        platform_set_drvdata(pdev, rtc);
+
+       s3c_rtc_setfreq(&pdev->dev, 1);
+
        return 0;
 
  err_nortc:
index 17da9ab932ed55d664f5f3bdbcab81447e83423e..a0ae29564774c7267654138e7a32beab87201f44 100644 (file)
@@ -42,7 +42,7 @@
  * size_t size;
  *
  * size = itcw_calc_size(1, 2, 0);
- * buffer = kmalloc(size, GFP_DMA);
+ * buffer = kmalloc(size, GFP_KERNEL | GFP_DMA);
  * if (!buffer)
  *     return -ENOMEM;
  * itcw = itcw_init(buffer, size, ITCW_OP_READ, 1, 2, 0);
index 18735b39b3d39c8547e27b8037fbef033a0df76a..3ddb4dc62d5d5eed49ecc1a1228ddbdfbecd1f47 100644 (file)
@@ -542,8 +542,11 @@ MODULE_DEVICE_TABLE (of, mac53c94_match);
 
 static struct macio_driver mac53c94_driver = 
 {
-       .name           = "mac53c94",
-       .match_table    = mac53c94_match,
+       .driver = {
+               .name           = "mac53c94",
+               .owner          = THIS_MODULE,
+               .of_match_table = mac53c94_match,
+       },
        .probe          = mac53c94_probe,
        .remove         = mac53c94_remove,
 };
index a1c97e88068ae961ce3605ecfe1143f2c80af7b3..1f784fde25109b53ef86f2b79fd975ed5cc2bf38 100644 (file)
@@ -2036,8 +2036,11 @@ MODULE_DEVICE_TABLE (of, mesh_match);
 
 static struct macio_driver mesh_driver = 
 {
-       .name           = "mesh",
-       .match_table    = mesh_match,
+       .driver = {
+               .name           = "mesh",
+               .owner          = THIS_MODULE,
+               .of_match_table = mesh_match,
+       },
        .probe          = mesh_probe,
        .remove         = mesh_remove,
        .shutdown       = mesh_shutdown,
index 829cc37abc41a57ad45715524a81730b60b7d4ba..8802e48bc063408710792451e95cab70ce4b1a0e 100644 (file)
@@ -97,6 +97,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 #endif
 
 static int  sd_revalidate_disk(struct gendisk *);
+static void sd_unlock_native_capacity(struct gendisk *disk);
 static int  sd_probe(struct device *);
 static int  sd_remove(struct device *);
 static void sd_shutdown(struct device *);
@@ -1101,6 +1102,7 @@ static const struct block_device_operations sd_fops = {
 #endif
        .media_changed          = sd_media_changed,
        .revalidate_disk        = sd_revalidate_disk,
+       .unlock_native_capacity = sd_unlock_native_capacity,
 };
 
 static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
@@ -2120,6 +2122,26 @@ static int sd_revalidate_disk(struct gendisk *disk)
        return 0;
 }
 
+/**
+ *     sd_unlock_native_capacity - unlock native capacity
+ *     @disk: struct gendisk to set capacity for
+ *
+ *     Block layer calls this function if it detects that partitions
+ *     on @disk reach beyond the end of the device.  If the SCSI host
+ *     implements ->unlock_native_capacity() method, it's invoked to
+ *     give it a chance to adjust the device capacity.
+ *
+ *     CONTEXT:
+ *     Defined by block layer.  Might sleep.
+ */
+static void sd_unlock_native_capacity(struct gendisk *disk)
+{
+       struct scsi_device *sdev = scsi_disk(disk)->device;
+
+       if (sdev->host->hostt->unlock_native_capacity)
+               sdev->host->hostt->unlock_native_capacity(sdev);
+}
+
 /**
  *     sd_format_disk_name - format disk name
  *     @prefix: name prefix - ie. "sd" for SCSI disks
index 01c012da4e26d01eef7c9cfeb87b71a26e1f1bd6..746a44621d9157e3a50448ce60e577d66dfc1246 100644 (file)
@@ -982,6 +982,18 @@ static int skip_tx_en_setup(struct serial_private *priv,
 #define PCI_SUBDEVICE_ID_POCTAL422     0x0408
 #define PCI_VENDOR_ID_ADVANTECH                0x13fe
 #define PCI_DEVICE_ID_ADVANTECH_PCI3620        0x3620
+#define PCI_DEVICE_ID_TITAN_200I       0x8028
+#define PCI_DEVICE_ID_TITAN_400I       0x8048
+#define PCI_DEVICE_ID_TITAN_800I       0x8088
+#define PCI_DEVICE_ID_TITAN_800EH      0xA007
+#define PCI_DEVICE_ID_TITAN_800EHB     0xA008
+#define PCI_DEVICE_ID_TITAN_400EH      0xA009
+#define PCI_DEVICE_ID_TITAN_100E       0xA010
+#define PCI_DEVICE_ID_TITAN_200E       0xA012
+#define PCI_DEVICE_ID_TITAN_400E       0xA013
+#define PCI_DEVICE_ID_TITAN_800E       0xA014
+#define PCI_DEVICE_ID_TITAN_200EI      0xA016
+#define PCI_DEVICE_ID_TITAN_200EISI    0xA017
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584        0x1584
@@ -1541,6 +1553,10 @@ enum pci_board_num_t {
        pbn_b3_4_115200,
        pbn_b3_8_115200,
 
+       pbn_b4_bt_2_921600,
+       pbn_b4_bt_4_921600,
+       pbn_b4_bt_8_921600,
+
        /*
         * Board-specific versions.
         */
@@ -1995,6 +2011,25 @@ static struct pciserial_board pci_boards[] __devinitdata = {
                .uart_offset    = 8,
        },
 
+       [pbn_b4_bt_2_921600] = {
+               .flags          = FL_BASE4,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b4_bt_4_921600] = {
+               .flags          = FL_BASE4,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+       [pbn_b4_bt_8_921600] = {
+               .flags          = FL_BASE4,
+               .num_ports      = 8,
+               .base_baud      = 921600,
+               .uart_offset    = 8,
+       },
+
        /*
         * Entries following this are board-specific.
         */
@@ -3043,6 +3078,42 @@ static struct pci_device_id serial_pci_tbl[] = {
        {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                pbn_b0_bt_8_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200I,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b4_bt_2_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400I,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b4_bt_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800I,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b4_bt_8_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400EH,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EH,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EHB,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b0_4_921600 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_1_4000000 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_2_4000000 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_4_4000000 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_8_4000000 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_2_4000000 },
+       {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_2_4000000 },
 
        {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
index bcee156d2f2eb32edc3f9f1d60a55e545875663a..0f1189605d2141b2516b48c6ecd6ed6ee7c287ec 100644 (file)
@@ -89,15 +89,12 @@ static unsigned int altera_uart_tx_empty(struct uart_port *port)
 static unsigned int altera_uart_get_mctrl(struct uart_port *port)
 {
        struct altera_uart *pp = container_of(port, struct altera_uart, port);
-       unsigned long flags;
        unsigned int sigs;
 
-       spin_lock_irqsave(&port->lock, flags);
        sigs =
            (readl(port->membase + ALTERA_UART_STATUS_REG) &
             ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
        sigs |= (pp->sigs & TIOCM_RTS);
-       spin_unlock_irqrestore(&port->lock, flags);
 
        return sigs;
 }
@@ -105,49 +102,37 @@ static unsigned int altera_uart_get_mctrl(struct uart_port *port)
 static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs)
 {
        struct altera_uart *pp = container_of(port, struct altera_uart, port);
-       unsigned long flags;
 
-       spin_lock_irqsave(&port->lock, flags);
        pp->sigs = sigs;
        if (sigs & TIOCM_RTS)
                pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
        else
                pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
        writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
-       spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static void altera_uart_start_tx(struct uart_port *port)
 {
        struct altera_uart *pp = container_of(port, struct altera_uart, port);
-       unsigned long flags;
 
-       spin_lock_irqsave(&port->lock, flags);
        pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
        writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
-       spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static void altera_uart_stop_tx(struct uart_port *port)
 {
        struct altera_uart *pp = container_of(port, struct altera_uart, port);
-       unsigned long flags;
 
-       spin_lock_irqsave(&port->lock, flags);
        pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
        writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
-       spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static void altera_uart_stop_rx(struct uart_port *port)
 {
        struct altera_uart *pp = container_of(port, struct altera_uart, port);
-       unsigned long flags;
 
-       spin_lock_irqsave(&port->lock, flags);
        pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
        writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
-       spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static void altera_uart_break_ctl(struct uart_port *port, int break_state)
@@ -272,10 +257,14 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data)
        unsigned int isr;
 
        isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr;
+
+       spin_lock(&port->lock);
        if (isr & ALTERA_UART_STATUS_RRDY_MSK)
                altera_uart_rx_chars(pp);
        if (isr & ALTERA_UART_STATUS_TRDY_MSK)
                altera_uart_tx_chars(pp);
+       spin_unlock(&port->lock);
+
        return IRQ_RETVAL(isr);
 }
 
@@ -402,31 +391,24 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)
        return 0;
 }
 
-static void altera_uart_console_putc(struct console *co, const char c)
+static void altera_uart_console_putc(struct uart_port *port, const char c)
 {
-       struct uart_port *port = &(altera_uart_ports + co->index)->port;
-       int i;
+       while (!(readl(port->membase + ALTERA_UART_STATUS_REG) &
+                ALTERA_UART_STATUS_TRDY_MSK))
+               cpu_relax();
 
-       for (i = 0; i < 0x10000; i++) {
-               if (readl(port->membase + ALTERA_UART_STATUS_REG) &
-                   ALTERA_UART_STATUS_TRDY_MSK)
-                       break;
-       }
        writel(c, port->membase + ALTERA_UART_TXDATA_REG);
-       for (i = 0; i < 0x10000; i++) {
-               if (readl(port->membase + ALTERA_UART_STATUS_REG) &
-                   ALTERA_UART_STATUS_TRDY_MSK)
-                       break;
-       }
 }
 
 static void altera_uart_console_write(struct console *co, const char *s,
                                      unsigned int count)
 {
+       struct uart_port *port = &(altera_uart_ports + co->index)->port;
+
        for (; count; count--, s++) {
-               altera_uart_console_putc(co, *s);
+               altera_uart_console_putc(port, *s);
                if (*s == '\n')
-                       altera_uart_console_putc(co, '\r');
+                       altera_uart_console_putc(port, '\r');
        }
 }
 
@@ -516,7 +498,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int altera_uart_remove(struct platform_device *pdev)
+static int __devexit altera_uart_remove(struct platform_device *pdev)
 {
        struct uart_port *port;
        int i;
index 96f7e7484feebf4269c631862f9a01b227eac0f6..511cbf68787782ce9b782f85ae51a0b5a80df5a6 100644 (file)
@@ -797,7 +797,7 @@ static void bfin_serial_shutdown(struct uart_port *port)
                gpio_free(uart->rts_pin);
 #endif
 #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
-       if (UART_GET_IER(uart) && EDSSI)
+       if (UART_GET_IER(uart) & EDSSI)
                free_irq(uart->status_irq, uart);
 #endif
 }
@@ -869,7 +869,12 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
        }
 
        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-       quot = uart_get_divisor(port, baud) - ANOMALY_05000230;
+       quot = uart_get_divisor(port, baud);
+
+       /* If discipline is not IRDA, apply ANOMALY_05000230 */
+       if (termios->c_line != N_IRDA)
+               quot -= ANOMALY_05000230;
+
        spin_lock_irqsave(&uart->port.lock, flags);
 
        UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
index 9eb62a256e9a675af529475d178c7925e6de5302..cd6cf575902e4aab43a2dc232c7358db93ff8a82 100644 (file)
@@ -930,6 +930,83 @@ static void cpm_uart_config_port(struct uart_port *port, int flags)
        }
 }
 
+#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_CPM_CONSOLE)
+/*
+ * Write a string to the serial port
+ * Note that this is called with interrupts already disabled
+ */
+static void cpm_uart_early_write(struct uart_cpm_port *pinfo,
+               const char *string, u_int count)
+{
+       unsigned int i;
+       cbd_t __iomem *bdp, *bdbase;
+       unsigned char *cpm_outp_addr;
+
+       /* Get the address of the host memory buffer.
+        */
+       bdp = pinfo->tx_cur;
+       bdbase = pinfo->tx_bd_base;
+
+       /*
+        * Now, do each character.  This is not as bad as it looks
+        * since this is a holding FIFO and not a transmitting FIFO.
+        * We could add the complexity of filling the entire transmit
+        * buffer, but we would just wait longer between accesses......
+        */
+       for (i = 0; i < count; i++, string++) {
+               /* Wait for transmitter fifo to empty.
+                * Ready indicates output is ready, and xmt is doing
+                * that, not that it is ready for us to send.
+                */
+               while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+                       ;
+
+               /* Send the character out.
+                * If the buffer address is in the CPM DPRAM, don't
+                * convert it.
+                */
+               cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+                                       pinfo);
+               *cpm_outp_addr = *string;
+
+               out_be16(&bdp->cbd_datlen, 1);
+               setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+               if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+                       bdp = bdbase;
+               else
+                       bdp++;
+
+               /* if a LF, also do CR... */
+               if (*string == 10) {
+                       while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+                               ;
+
+                       cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+                                               pinfo);
+                       *cpm_outp_addr = 13;
+
+                       out_be16(&bdp->cbd_datlen, 1);
+                       setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+                       if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+                               bdp = bdbase;
+                       else
+                               bdp++;
+               }
+       }
+
+       /*
+        * Finally, Wait for transmitter & holding register to empty
+        *  and restore the IER
+        */
+       while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+               ;
+
+       pinfo->tx_cur = bdp;
+}
+#endif
+
 #ifdef CONFIG_CONSOLE_POLL
 /* Serial polling routines for writing and reading from the uart while
  * in an interrupt or debug context.
@@ -999,7 +1076,7 @@ static void cpm_put_poll_char(struct uart_port *port,
        static char ch[2];
 
        ch[0] = (char)c;
-       cpm_uart_early_write(pinfo->port.line, ch, 1);
+       cpm_uart_early_write(pinfo, ch, 1);
 }
 #endif /* CONFIG_CONSOLE_POLL */
 
@@ -1130,9 +1207,6 @@ static void cpm_uart_console_write(struct console *co, const char *s,
                                   u_int count)
 {
        struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
-       unsigned int i;
-       cbd_t __iomem *bdp, *bdbase;
-       unsigned char *cp;
        unsigned long flags;
        int nolock = oops_in_progress;
 
@@ -1142,66 +1216,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
                spin_lock_irqsave(&pinfo->port.lock, flags);
        }
 
-       /* Get the address of the host memory buffer.
-        */
-       bdp = pinfo->tx_cur;
-       bdbase = pinfo->tx_bd_base;
-
-       /*
-        * Now, do each character.  This is not as bad as it looks
-        * since this is a holding FIFO and not a transmitting FIFO.
-        * We could add the complexity of filling the entire transmit
-        * buffer, but we would just wait longer between accesses......
-        */
-       for (i = 0; i < count; i++, s++) {
-               /* Wait for transmitter fifo to empty.
-                * Ready indicates output is ready, and xmt is doing
-                * that, not that it is ready for us to send.
-                */
-               while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
-                       ;
-
-               /* Send the character out.
-                * If the buffer address is in the CPM DPRAM, don't
-                * convert it.
-                */
-               cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
-               *cp = *s;
-
-               out_be16(&bdp->cbd_datlen, 1);
-               setbits16(&bdp->cbd_sc, BD_SC_READY);
-
-               if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
-                       bdp = bdbase;
-               else
-                       bdp++;
-
-               /* if a LF, also do CR... */
-               if (*s == 10) {
-                       while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
-                               ;
-
-                       cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
-                       *cp = 13;
-
-                       out_be16(&bdp->cbd_datlen, 1);
-                       setbits16(&bdp->cbd_sc, BD_SC_READY);
-
-                       if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
-                               bdp = bdbase;
-                       else
-                               bdp++;
-               }
-       }
-
-       /*
-        * Finally, Wait for transmitter & holding register to empty
-        *  and restore the IER
-        */
-       while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
-               ;
-
-       pinfo->tx_cur = bdp;
+       cpm_uart_early_write(pinfo, s, count);
 
        if (unlikely(nolock)) {
                local_irq_restore(flags);
index ecdc0facf7ee9928fd4354a0e2a52e5d611b6acb..f8c816e7725de2152f9f80b50a0962c6f88c82e4 100644 (file)
@@ -41,19 +41,6 @@ struct msm_port {
        unsigned int            imr;
 };
 
-#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
-
-static inline void msm_write(struct uart_port *port, unsigned int val,
-                            unsigned int off)
-{
-       __raw_writel(val, port->membase + off);
-}
-
-static inline unsigned int msm_read(struct uart_port *port, unsigned int off)
-{
-       return __raw_readl(port->membase + off);
-}
-
 static void msm_stop_tx(struct uart_port *port)
 {
        struct msm_port *msm_port = UART_TO_MSM(port);
@@ -320,11 +307,7 @@ static void msm_init_clock(struct uart_port *port)
        struct msm_port *msm_port = UART_TO_MSM(port);
 
        clk_enable(msm_port->clk);
-
-       msm_write(port, 0xC0, UART_MREG);
-       msm_write(port, 0xB2, UART_NREG);
-       msm_write(port, 0x7D, UART_DREG);
-       msm_write(port, 0x1C, UART_MNDREG);
+       msm_serial_set_mnd_regs(port);
 }
 
 static int msm_startup(struct uart_port *port)
@@ -706,6 +689,8 @@ static int __init msm_serial_probe(struct platform_device *pdev)
        if (unlikely(IS_ERR(msm_port->clk)))
                return PTR_ERR(msm_port->clk);
        port->uartclk = clk_get_rate(msm_port->clk);
+       printk(KERN_INFO "uartclk = %d\n", port->uartclk);
+
 
        resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (unlikely(!resource))
index 689f1fa0e84e2370254bc0570e7a841e98184b23..f6ca9ca79e98f34be24525596f1b38fe5c5f31a3 100644 (file)
 #define UART_MISR      0x0010
 #define UART_ISR       0x0014
 
+#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
+
+static inline
+void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
+{
+       __raw_writel(val, port->membase + off);
+}
+
+static inline
+unsigned int msm_read(struct uart_port *port, unsigned int off)
+{
+       return __raw_readl(port->membase + off);
+}
+
+/*
+ * Setup the MND registers to use the TCXO clock.
+ */
+static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
+{
+       msm_write(port, 0x06, UART_MREG);
+       msm_write(port, 0xF1, UART_NREG);
+       msm_write(port, 0x0F, UART_DREG);
+       msm_write(port, 0x1A, UART_MNDREG);
+}
+
+/*
+ * Setup the MND registers to use the TCXO clock divided by 4.
+ */
+static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
+{
+       msm_write(port, 0x18, UART_MREG);
+       msm_write(port, 0xF6, UART_NREG);
+       msm_write(port, 0x0F, UART_DREG);
+       msm_write(port, 0x0A, UART_MNDREG);
+}
+
+static inline
+void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
+{
+       if (port->uartclk == 19200000)
+               msm_serial_set_mnd_regs_tcxo(port);
+       else
+               msm_serial_set_mnd_regs_tcxoby4(port);
+}
+
+/*
+ * TROUT has a specific defect that makes it report it's uartclk
+ * as 19.2Mhz (TCXO) when it's actually 4.8Mhz (TCXO/4). This special
+ * cases TROUT to use the right clock.
+ */
+#ifdef CONFIG_MACH_TROUT
+#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_tcxoby4
+#else
+#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_from_uartclk
+#endif
+
 #endif /* __DRIVERS_SERIAL_MSM_SERIAL_H */
index cabbdc7ba5838bf62e1fa799a6ed2678eb650864..5b9cde79e4eaf5c3f686f7b056952e04b1eef027 100644 (file)
@@ -2005,8 +2005,11 @@ static struct of_device_id pmz_match[] =
 MODULE_DEVICE_TABLE (of, pmz_match);
 
 static struct macio_driver pmz_driver = {
-       .name           = "pmac_zilog",
-       .match_table    = pmz_match,
+       .driver = {
+               .name           = "pmac_zilog",
+               .owner          = THIS_MODULE,
+               .of_match_table = pmz_match,
+       },
        .probe          = pmz_attach,
        .remove         = pmz_detach,
        .suspend        = pmz_suspend,
index dadd686c98012e545bf90d07a61447853630818d..ab17c08ddc03cac3fcc6674dba53bd2a4e9960a9 100644 (file)
@@ -715,6 +715,8 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
        PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
        PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
        PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
        PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
        PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
@@ -724,8 +726,6 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
        PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
        PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
-       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
        PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
        PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
        PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
@@ -768,17 +768,26 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
        PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
        PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
+       PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0101), /* TDK DF2814 */
+       PCMCIA_DEVICE_MANF_CARD(0x0105, 0x100a), /* Xircom CM-56G */
+       PCMCIA_DEVICE_MANF_CARD(0x0105, 0x3e0a), /* TDK DF5660 */
        PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
+       PCMCIA_DEVICE_MANF_CARD(0x0107, 0x0002), /* USRobotics 14,400 */
        PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
        PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
        PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
        PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
        PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
+       PCMCIA_DEVICE_MANF_CARD(0x0115, 0x3330), /* USRobotics/SUN 14,400 */
+       PCMCIA_DEVICE_MANF_CARD(0x0124, 0x0100), /* Nokia DTP-2 ver II */
+       PCMCIA_DEVICE_MANF_CARD(0x0134, 0x5600), /* LASAT COMMUNICATIONS A/S */
        PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
        PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
        PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
        PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
        PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
+       PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0006), /* Psion 56K+Fax */
+       PCMCIA_DEVICE_MANF_CARD(0x0200, 0x0001), /* MultiMobile */
        PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
        PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
        PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
@@ -792,21 +801,27 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
        PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
        PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
+       PCMCIA_DEVICE_PROD_ID12("IBM", "ISDN/56K/GSM", 0xb569a6e5, 0xfee5297b),
        PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
        PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
+       PCMCIA_DEVICE_PROD_ID12("Intertex", "IX34-PCMCIA", 0xf8a097e3, 0x97880447),
        PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
        PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
        PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
        PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
        PCMCIA_DEVICE_PROD_ID12("OEM      ", "C288MX     ", 0xb572d360, 0xd2385b7a),
+       PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41),
        PCMCIA_DEVICE_PROD_ID12("PCMCIA   ", "C336MX     ", 0x99bcafe9, 0xaa25bcab),
        PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
        PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
+       PCMCIA_DEVICE_PROD_ID12("Telia", "SurfinBird 560P/A+", 0xe2cdd5e, 0xc9314b38),
+       PCMCIA_DEVICE_PROD_ID1("Smart Serial Port", 0x2d8ce292),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
index 005195958647b03acded28a822bfd7374744d210..ceba593dc84fbcb994f1fb4968cab3b4adf05b83 100644 (file)
@@ -441,8 +441,10 @@ struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa)
 
        ret = sysfs_create_bin_file(tables_kobj,
                                  &tbl_attr->attr);
-       if (ret)
+       if (ret) {
                kfree(tbl_attr);
+               tbl_attr = NULL;
+       }
 
        sfi_unmap_table(th);
        return tbl_attr;
index c585574b9aedcc6b5c25fc6db620959a61a9ad08..e91a23e5ffd8ad874a8f2e8c6615b5e181a54f8c 100644 (file)
@@ -16,6 +16,8 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/module.h>
@@ -855,8 +857,8 @@ static void __init intc_register_irq(struct intc_desc *desc,
                primary = 1;
 
        if (!data[0] && !data[1])
-               pr_warning("intc: missing unique irq mask for "
-                          "irq %d (vect 0x%04x)\n", irq, irq2evt(irq));
+               pr_warning("missing unique irq mask for irq %d (vect 0x%04x)\n",
+                          irq, irq2evt(irq));
 
        data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1);
        data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1);
@@ -952,7 +954,7 @@ int __init register_intc_controller(struct intc_desc *desc)
        struct intc_desc_int *d;
        struct resource *res;
 
-       pr_info("intc: Registered controller '%s' with %u IRQs\n",
+       pr_info("Registered controller '%s' with %u IRQs\n",
                desc->name, hw->nr_vectors);
 
        d = kzalloc(sizeof(*d), GFP_NOWAIT);
@@ -1148,7 +1150,7 @@ int register_intc_userimask(unsigned long addr)
        if (unlikely(!uimask))
                return -ENOMEM;
 
-       pr_info("intc: userimask support registered for levels 0 -> %d\n",
+       pr_info("userimask support registered for levels 0 -> %d\n",
                default_prio_level - 1);
 
        return 0;
@@ -1286,7 +1288,7 @@ static int __init register_intc_sysdevs(void)
        }
 
        if (error)
-               pr_err("intc: sysdev registration error\n");
+               pr_err("sysdev registration error\n");
 
        return error;
 }
index 28a126d2742bcf1fd89e1f753080341dfe4958a3..2534b1ec3eddc5b39485c8fa71fff21dcbef07d3 100644 (file)
@@ -512,29 +512,29 @@ static int __init mpc512x_psc_spi_of_probe(struct of_device *op,
        u64 regaddr64, size64;
        s16 id = -1;
 
-       regaddr_p = of_get_address(op->node, 0, &size64, NULL);
+       regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
        if (!regaddr_p) {
                dev_err(&op->dev, "Invalid PSC address\n");
                return -EINVAL;
        }
-       regaddr64 = of_translate_address(op->node, regaddr_p);
+       regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
 
        /* get PSC id (0..11, used by port_config) */
        if (op->dev.platform_data == NULL) {
                const u32 *psc_nump;
 
-               psc_nump = of_get_property(op->node, "cell-index", NULL);
+               psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL);
                if (!psc_nump || *psc_nump > 11) {
                        dev_err(&op->dev, "mpc512x_psc_spi: Device node %s "
                                "has invalid cell-index property\n",
-                               op->node->full_name);
+                               op->dev.of_node->full_name);
                        return -EINVAL;
                }
                id = *psc_nump;
        }
 
        return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
-                                       irq_of_parse_and_map(op->node, 0), id);
+                               irq_of_parse_and_map(op->dev.of_node, 0), id);
 }
 
 static int __exit mpc512x_psc_spi_of_remove(struct of_device *op)
@@ -550,12 +550,12 @@ static struct of_device_id mpc512x_psc_spi_of_match[] = {
 MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
 
 static struct of_platform_driver mpc512x_psc_spi_of_driver = {
-       .match_table = mpc512x_psc_spi_of_match,
        .probe = mpc512x_psc_spi_of_probe,
        .remove = __exit_p(mpc512x_psc_spi_of_remove),
        .driver = {
                .name = "mpc512x-psc-spi",
                .owner = THIS_MODULE,
+               .of_match_table = mpc512x_psc_spi_of_match,
        },
 };
 
index 19c0b3b34fce0160d7cb4d0b0c16f14d8143671d..d53466a249d9700bb9108478a5b08ffcf1955b6a 100644 (file)
@@ -397,7 +397,7 @@ static int __init spi_ppc4xx_of_probe(struct of_device *op,
        struct spi_master *master;
        struct spi_bitbang *bbp;
        struct resource resource;
-       struct device_node *np = op->node;
+       struct device_node *np = op->dev.of_node;
        struct device *dev = &op->dev;
        struct device_node *opbnp;
        int ret;
index 989e2752cc36d8abb9613b6c77b50936be85184c..6dcda86be6ebdb83d579d27907ee1f153889000a 100644 (file)
@@ -625,9 +625,12 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
                ssb_printk(KERN_ERR PFX "No SPROM available!\n");
                return -ENODEV;
        }
-
-       bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
-               SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
+       if (bus->chipco.dev) {  /* can be unavailible! */
+               bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
+                       SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
+       } else {
+               bus->sprom_offset = SSB_SPROM_BASE1;
+       }
 
        buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
        if (!buf)
index 007bc3a03486b621034134f33a1c3029cb8e0b29..4f7cc8d13277ddb84126430923202f9fa7938ac7 100644 (file)
@@ -185,6 +185,7 @@ bool ssb_is_sprom_available(struct ssb_bus *bus)
        /* this routine differs from specs as we do not access SPROM directly
           on PCMCIA */
        if (bus->bustype == SSB_BUSTYPE_PCI &&
+           bus->chipco.dev &&  /* can be unavailible! */
            bus->chipco.dev->id.revision >= 31)
                return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM;
 
index b5c3b3013037c0eccb099c9ccff17e4ac557d1eb..984a75440710673efe2c50ea5967c460a7ef3d12 100644 (file)
@@ -141,5 +141,11 @@ source "drivers/staging/ti-st/Kconfig"
 
 source "drivers/staging/adis16255/Kconfig"
 
+source "drivers/staging/xgifb/Kconfig"
+
+source "drivers/staging/mrst-touchscreen/Kconfig"
+
+source "drivers/staging/msm/Kconfig"
+
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
index e330dd5e843d510178895bca75aed1741e0372a3..9fa25133874afc9b0c2a4c4b31a87f0aa98468d3 100644 (file)
@@ -51,3 +51,6 @@ obj-$(CONFIG_CRYSTALHD)               += crystalhd/
 obj-$(CONFIG_CXT1E1)           += cxt1e1/
 obj-$(CONFIG_TI_ST)            += ti-st/
 obj-$(CONFIG_ADIS16255)                += adis16255/
+obj-$(CONFIG_FB_XGI)           += xgifb/
+obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH)     += mrst-touchscreen/
+obj-$(CONFIG_MSM_STAGING)      += msm/
index a642be66adeac6f85089470bb8d7697c115de16b..a883c1f4478bd089524824d0a5346daacfe83c6f 100644 (file)
@@ -1,5 +1,5 @@
 config ADIS16255
-       tristate "Ananlog Devices ADIS16250/16255"
+       tristate "Analog Devices ADIS16250/16255"
        depends on SPI && SYSFS
        ---help---
        If you say yes here you get support for the Analog Devices
index 1ba11f00b2e726fa8d4d070eb9a1e0fdc535b88f..55d66e290f7d1d80eb0e1603c12b4b7224031c0e 100644 (file)
@@ -361,7 +361,7 @@ err:
 
 /*-------------------------------------------------------------------------*/
 
-static int spi_adis16255_probe(struct spi_device *spi)
+static int __devinit spi_adis16255_probe(struct spi_device *spi)
 {
 
        struct adis16255_init_data *init_data = spi->dev.platform_data;
@@ -421,7 +421,7 @@ err:
        return status;
 }
 
-static int spi_adis16255_remove(struct spi_device *spi)
+static int __devexit spi_adis16255_remove(struct spi_device *spi)
 {
        struct spi_adis16255_data  *spiadis    = dev_get_drvdata(&spi->dev);
 
index e2c000b80ca0e41b998be612c4f570116ad28357..212bc21e6d682f7b3e822856be86c1af6f916102 100644 (file)
@@ -225,9 +225,9 @@ static struct bat_attribute *mesh_attrs[] = {
        NULL,
 };
 
-static ssize_t transtable_local_read(struct kobject *kobj,
-                              struct bin_attribute *bin_attr,
-                              char *buff, loff_t off, size_t count)
+static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
+                                 char *buff, loff_t off, size_t count)
 {
        struct device *dev = to_dev(kobj->parent);
        struct net_device *net_dev = to_net_dev(dev);
@@ -235,9 +235,9 @@ static ssize_t transtable_local_read(struct kobject *kobj,
        return hna_local_fill_buffer_text(net_dev, buff, count, off);
 }
 
-static ssize_t transtable_global_read(struct kobject *kobj,
-                              struct bin_attribute *bin_attr,
-                              char *buff, loff_t off, size_t count)
+static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
+                                 char *buff, loff_t off, size_t count)
 {
        struct device *dev = to_dev(kobj->parent);
        struct net_device *net_dev = to_net_dev(dev);
@@ -245,9 +245,9 @@ static ssize_t transtable_global_read(struct kobject *kobj,
        return hna_global_fill_buffer_text(net_dev, buff, count, off);
 }
 
-static ssize_t originators_read(struct kobject *kobj,
-                              struct bin_attribute *bin_attr,
-                              char *buff, loff_t off, size_t count)
+static ssize_t originators_read(struct file *filp, struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
+                                 char *buff, loff_t off, size_t count)
 {
        struct device *dev = to_dev(kobj->parent);
        struct net_device *net_dev = to_net_dev(dev);
@@ -255,9 +255,9 @@ static ssize_t originators_read(struct kobject *kobj,
        return orig_fill_buffer_text(net_dev, buff, count, off);
 }
 
-static ssize_t vis_data_read(struct kobject *kobj,
-                            struct bin_attribute *bin_attr,
-                            char *buff, loff_t off, size_t count)
+static ssize_t vis_data_read(struct file *filp, struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
+                                 char *buff, loff_t off, size_t count)
 {
        struct device *dev = to_dev(kobj->parent);
        struct net_device *net_dev = to_net_dev(dev);
index ad82ec4a48562d9f44fcba08cd767931764af220..32204b5572d0c8e78a34b89c69a04c6d11cb762c 100644 (file)
@@ -196,7 +196,7 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
        kfree(device_packet);
 
        if (error)
-               return error;
+               return -EFAULT;
 
        return sizeof(struct icmp_packet);
 }
@@ -309,7 +309,7 @@ void bat_device_add_packet(struct device_client *device_client,
        struct device_packet *device_packet;
        unsigned long flags;
 
-       device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL);
+       device_packet = kmalloc(sizeof(struct device_packet), GFP_ATOMIC);
 
        if (!device_packet)
                return;
index 9d13979c2d8ee071d8f29442d03ccc05bc8b64a5..74c70d589a932d1d42ed249d3b9b04c0558d276b 100644 (file)
@@ -127,7 +127,10 @@ int init_module(void)
        return 0;
 
 unreg_soft_device:
-       unregister_netdevice(soft_device);
+       unregister_netdev(soft_device);
+       soft_device = NULL;
+       return -ENOMEM;
+
 free_soft_device:
        free_netdev(soft_device);
        soft_device = NULL;
index d8536e277a26163c27e44f47f185154e58f249aa..ac69ed871a7614c36b8bfc1d2bda10cb1792b14b 100644 (file)
@@ -440,6 +440,9 @@ void send_outstanding_bcast_packet(struct work_struct *work)
        hlist_del(&forw_packet->list);
        spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
 
+       if (atomic_read(&module_state) == MODULE_DEACTIVATING)
+               goto out;
+
        /* rebroadcast packet */
        rcu_read_lock();
        list_for_each_entry_rcu(batman_if, &if_list, list) {
@@ -453,15 +456,15 @@ void send_outstanding_bcast_packet(struct work_struct *work)
 
        forw_packet->num_packets++;
 
-       /* if we still have some more bcasts to send and we are not shutting
-        * down */
-       if ((forw_packet->num_packets < 3) &&
-           (atomic_read(&module_state) != MODULE_DEACTIVATING))
+       /* if we still have some more bcasts to send */
+       if (forw_packet->num_packets < 3) {
                _add_bcast_packet_to_list(forw_packet, ((5 * HZ) / 1000));
-       else {
-               forw_packet_free(forw_packet);
-               atomic_inc(&bcast_queue_left);
+               return;
        }
+
+out:
+       forw_packet_free(forw_packet);
+       atomic_inc(&bcast_queue_left);
 }
 
 void send_outstanding_bat_packet(struct work_struct *work)
@@ -476,6 +479,9 @@ void send_outstanding_bat_packet(struct work_struct *work)
        hlist_del(&forw_packet->list);
        spin_unlock_irqrestore(&forw_bat_list_lock, flags);
 
+       if (atomic_read(&module_state) == MODULE_DEACTIVATING)
+               goto out;
+
        send_packet(forw_packet);
 
        /**
@@ -483,10 +489,10 @@ void send_outstanding_bat_packet(struct work_struct *work)
         * to determine the queues wake up time unless we are
         * shutting down
         */
-       if ((forw_packet->own) &&
-           (atomic_read(&module_state) != MODULE_DEACTIVATING))
+       if (forw_packet->own)
                schedule_own_packet(forw_packet->if_incoming);
 
+out:
        /* don't count own packet */
        if (!forw_packet->own)
                atomic_inc(&batman_queue_left);
index 8ce307e64b58512d1a1f7fecb13caec8f82c684d..aad47326d6dc4b9422a97f385c58900387a8e9cc 100644 (file)
@@ -100,15 +100,6 @@ menuconfig COMEDI_ISA_DRIVERS
 
 if COMEDI_ISA_DRIVERS && ISA
 
-config COMEDI_8255
-       tristate "Generic 8255 support"
-       default N
-       ---help---
-         Enable generic 8255 support.
-
-         To compile this driver as a module, choose M here: the module will be
-         called 8255.
-
 config COMEDI_ACL7225B
        tristate "ADlink NuDAQ ACL-7225b and compatibles support"
        default N
@@ -130,6 +121,7 @@ config COMEDI_PCL711
 
 config COMEDI_PCL724
        tristate "Advantech PCL-722/724/731 and ADlink ACL-7122/7124/PET-48DIO"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for Advantech PCL-724, PCL-722, PCL-731 and
@@ -198,6 +190,7 @@ config COMEDI_PCL818
 
 config COMEDI_PCM3724
        tristate "Advantech PCM-3724 PC/104 card support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for Advantech PCM-3724 PC/104 cards.
@@ -232,18 +225,9 @@ config COMEDI_RTI802
          To compile this driver as a module, choose M here: the module will be
          called rti802.
 
-config COMEDI_DAS08
-       tristate "DAS-08 compatible ISA, PC/104 and PCMCIA card support"
-       default N
-       ---help---
-         Enable support for Keithley Metrabyte/ComputerBoards DAS08
-         and compatible ISA and PC/104 cards
-
-         To compile this driver as a module, choose M here: the module will be
-         called das08.
-
 config COMEDI_DAS16M1
        tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support"
+       select COMEDI_8255
        select COMEDI_FC
        default N
        ---help---
@@ -254,6 +238,7 @@ config COMEDI_DAS16M1
 
 config COMEDI_DAS16
        tristate "DAS-16 compatible ISA and PC/104 card support"
+       select COMEDI_8255
        select COMEDI_FC
        default N
        ---help---
@@ -385,6 +370,7 @@ config COMEDI_FL512
 
 config COMEDI_AIO_AIO12_8
        tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board
@@ -466,6 +452,7 @@ config COMEDI_NI_ATMIO
 config COMEDI_NI_ATMIO16D
        tristate "NI AT-MIO16/AT-MIO16D series ISA-PNP card support"
        depends on ISAPNP && COMEDI_NI_COMMON
+       select COMEDI_8255
        default N
        ---help---
          Enable support for National Instruments AT-MIO16/AT-MIO16D cards.
@@ -667,6 +654,7 @@ config COMEDI_ADDI_APCI_3XXX
 
 config COMEDI_ADL_PCI6208
        tristate "ADLink PCI-6208A support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for ADLink PCI-6208A cards
@@ -751,6 +739,7 @@ config COMEDI_ADV_PCI1723
 
 config COMEDI_ADV_PCI_DIO
        tristate "Advantech PCI DIO card support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for Advantech PCI DIO cards
@@ -762,6 +751,7 @@ config COMEDI_ADV_PCI_DIO
 
 config COMEDI_AMPLC_DIO200
        tristate "Amplicon PC272E and PCI272 DIO board support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for Amplicon PC272E and PCI272 DIO boards
@@ -771,6 +761,7 @@ config COMEDI_AMPLC_DIO200
 
 config COMEDI_AMPLC_PC236
        tristate "Amplicon PC36AT and PCI236 DIO board support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for Amplicon PC36AT and PCI236 DIO boards
@@ -799,6 +790,7 @@ config COMEDI_AMPLC_PCI224
 
 config COMEDI_AMPLC_PCI230
        tristate "Amplicon PCI230 and PCI260 support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for Amplicon PCI230 and PCI260 Multifunction I/O
@@ -869,6 +861,7 @@ config COMEDI_II_PCI20KC
 
 config COMEDI_DAQBOARD2000
        tristate "IOtech DAQboard/2000 support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for the IOtech DAQboard/2000
@@ -896,6 +889,7 @@ config COMEDI_KE_COUNTER
 
 config COMEDI_CB_PCIDAS64
        tristate "MeasurementComputing PCI-DAS 64xx, 60xx, and 4020 support"
+       select COMEDI_8255
        select COMEDI_FC
        default N
        ---help---
@@ -907,6 +901,7 @@ config COMEDI_CB_PCIDAS64
 
 config COMEDI_CB_PCIDAS
        tristate "MeasurementComputing PCI-DAS support"
+       select COMEDI_8255
        select COMEDI_FC
        default N
        ---help---
@@ -920,6 +915,7 @@ config COMEDI_CB_PCIDAS
 
 config COMEDI_CB_PCIDDA
        tristate "MeasurementComputing PCI-DDA series support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for ComputerBoards/MeasurementComputing PCI-DDA
@@ -931,6 +927,7 @@ config COMEDI_CB_PCIDDA
 
 config COMEDI_CB_PCIDIO
        tristate "MeasurementComputing PCI-DIO series support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for ComputerBoards/MeasurementComputing PCI-DIO series
@@ -941,6 +938,7 @@ config COMEDI_CB_PCIDIO
 
 config COMEDI_CB_PCIMDAS
        tristate "MeasurementComputing PCIM-DAS1602/16 support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for ComputerBoards/MeasurementComputing PCI Migration
@@ -951,6 +949,7 @@ config COMEDI_CB_PCIMDAS
 
 config COMEDI_CB_PCIMDDA
        tristate "MeasurementComputing PCIM-DDA06-16 support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for ComputerBoards/MeasurementComputing PCIM-DDA06-16
@@ -1026,6 +1025,7 @@ config COMEDI_NI_670X
 config COMEDI_NI_PCIDIO
        tristate "NI PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503 support"
        depends on COMEDI_MITE
+       select COMEDI_8255
        default N
        ---help---
          Enable support for National Instruments PCI-DIO-32HS, PXI-6533,
@@ -1058,6 +1058,7 @@ config COMEDI_NI_PCIMIO
 
 config COMEDI_RTD520
        tristate "Real Time Devices PCI4520/DM7520 support"
+       select COMEDI_8255
        default N
        ---help---
          Enable support for Real Time Devices PCI4520/DM7520
@@ -1097,7 +1098,7 @@ endif # COMEDI_PCI_DRIVERS
 
 menuconfig COMEDI_PCMCIA_DRIVERS
        tristate "Comedi PCMCIA drivers"
-       depends on COMEDI && PCMCIA && PCCARD
+       depends on COMEDI && (PCMCIA || PCCARD)
        default N
        ---help---
          Enable comedi PCMCIA and PCCARD drivers to be built
@@ -1142,6 +1143,7 @@ config COMEDI_NI_DAQ_700_CS
 config COMEDI_NI_DAQ_DIO24_CS
        tristate "NI DAQ-Card DIO-24 PCMCIA support"
        depends on COMEDI_NI_COMMON
+       select COMEDI_8255
        default N
        ---help---
          Enable support for the National Instruments PCMCIA DAQ-Card DIO-24
@@ -1162,8 +1164,8 @@ config COMEDI_NI_LABPC_CS
 config COMEDI_NI_MIO_CS
        tristate "NI DAQCard E series PCMCIA support"
        depends on COMEDI_NI_TIO && COMEDI_NI_COMMON
-       default N
        select COMEDI_FC
+       default N
        ---help---
          Enable support for the National Instruments PCMCIA DAQCard E series
          DAQCard-ai-16xe-50, DAQCard-ai-16e-4, DAQCard-6062E, DAQCard-6024E
@@ -1265,7 +1267,8 @@ config COMEDI_MITE
 
 config COMEDI_NI_TIO
        tristate "NI general purpose counter support"
-       select COMEDI_MITE
+       depends on COMEDI_MITE
+       select COMEDI_8255
        default N
        ---help---
          Enable support for National Instruments general purpose counters.
@@ -1278,6 +1281,8 @@ config COMEDI_NI_TIO
 
 config COMEDI_NI_LABPC
        tristate "NI Lab-PC and compatibles ISA and PCI support"
+       depends on COMEDI_MITE
+       select COMEDI_8255
        select COMEDI_FC
        default N
        ---help---
@@ -1291,8 +1296,40 @@ config COMEDI_NI_LABPC
 
 endif # COMEDI_NI_COMMON
 
+config COMEDI_8255
+       tristate "Generic 8255 support"
+       depends on COMEDI
+       default N
+       ---help---
+         Enable generic 8255 support.
+
+         You should enable compilation this driver if you plan to use a board
+         that has an 8255 chip. For multifunction boards, the main driver will
+         configure the 8255 subdevice automatically.
+
+         Note that most PCI 8255 boards do NOT work with this driver, and
+         need a separate driver as a wrapper.
+
+         To compile this driver as a module, choose M here: the module will be
+         called 8255.
+
+config COMEDI_DAS08
+       tristate "DAS-08 compatible support"
+       depends on COMEDI
+       select COMEDI_8255
+       default N
+       ---help---
+         Enable support for DAS08 and compatible ISA, PC/104 and PCI cards.
+
+         Note that PCMCIA DAS08 cards are not directly supported by this
+         driver, and need a separate driver as a wrapper.
+
+         To compile this driver as a module, choose M here: the module will be
+         called das08.
+
 config COMEDI_FC
        tristate "Comedi shared functions for low-level driver support"
+       depends on COMEDI
        default N
        ---help---
          Enable support for shared functions for low-level drivers.
index aced00e5cd107ae03b7c5e4edc81f1135aa711cc..aeb2c00875cd2110117afae796edb95748134e39 100644 (file)
@@ -83,7 +83,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev,
 static int do_chaninfo_ioctl(struct comedi_device *dev,
                             struct comedi_chaninfo __user *arg);
 static int do_bufinfo_ioctl(struct comedi_device *dev,
-                           struct comedi_bufinfo __user *arg);
+                           struct comedi_bufinfo __user *arg, void *file);
 static int do_cmd_ioctl(struct comedi_device *dev,
                        struct comedi_cmd __user *arg, void *file);
 static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
@@ -169,7 +169,8 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
                break;
        case COMEDI_BUFINFO:
                rc = do_bufinfo_ioctl(dev,
-                                     (struct comedi_bufinfo __user *)arg);
+                                     (struct comedi_bufinfo __user *)arg,
+                                     file);
                break;
        case COMEDI_LOCK:
                rc = do_lock_ioctl(dev, arg, file);
@@ -563,7 +564,7 @@ static int do_chaninfo_ioctl(struct comedi_device *dev,
 
   */
 static int do_bufinfo_ioctl(struct comedi_device *dev,
-                           struct comedi_bufinfo __user *arg)
+                           struct comedi_bufinfo __user *arg, void *file)
 {
        struct comedi_bufinfo bi;
        struct comedi_subdevice *s;
@@ -576,6 +577,10 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
                return -EINVAL;
 
        s = dev->subdevices + bi.subdevice;
+
+       if (s->lock && s->lock != file)
+               return -EACCES;
+
        async = s->async;
 
        if (!async) {
@@ -584,8 +589,17 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
                bi.buf_read_ptr = 0;
                bi.buf_write_count = 0;
                bi.buf_read_count = 0;
+               bi.bytes_read = 0;
+               bi.bytes_written = 0;
                goto copyback;
        }
+       if (!s->busy) {
+               bi.bytes_read = 0;
+               bi.bytes_written = 0;
+               goto copyback_position;
+       }
+       if (s->busy != file)
+               return -EACCES;
 
        if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) {
                bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read);
@@ -604,6 +618,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
                comedi_buf_write_free(async, bi.bytes_written);
        }
 
+copyback_position:
        bi.buf_write_count = async->buf_write_count;
        bi.buf_write_ptr = async->buf_write_ptr;
        bi.buf_read_count = async->buf_read_count;
@@ -1576,6 +1591,19 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
        while (nbytes > 0 && !retval) {
                set_current_state(TASK_INTERRUPTIBLE);
 
+               if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
+                       if (count == 0) {
+                               if (comedi_get_subdevice_runflags(s) &
+                                       SRF_ERROR) {
+                                       retval = -EPIPE;
+                               } else {
+                                       retval = 0;
+                               }
+                               do_become_nonbusy(dev, s);
+                       }
+                       break;
+               }
+
                n = nbytes;
 
                m = n;
@@ -1588,16 +1616,6 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
                        n = m;
 
                if (n == 0) {
-                       if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
-                               if (comedi_get_subdevice_runflags(s) &
-                                   SRF_ERROR) {
-                                       retval = -EPIPE;
-                               } else {
-                                       retval = 0;
-                               }
-                               do_become_nonbusy(dev, s);
-                               break;
-                       }
                        if (file->f_flags & O_NONBLOCK) {
                                retval = -EAGAIN;
                                break;
index 5ccf246e2526c93fd2fe0dcab89f01c81faf7e40..354fb7d29841f400b7eaca46d7e4feaa41c3d8a8 100644 (file)
@@ -12,7 +12,6 @@ obj-$(CONFIG_COMEDI_SERIAL2002)               += serial2002.o
 obj-$(CONFIG_COMEDI_SKEL)              += skel.o
 
 # Comedi ISA drivers
-obj-$(CONFIG_COMEDI_8255)              += 8255.o
 obj-$(CONFIG_COMEDI_ACL7225B)          += acl7225b.o
 obj-$(CONFIG_COMEDI_PCL711)            += pcl711.o
 obj-$(CONFIG_COMEDI_PCL724)            += pcl724.o
@@ -26,7 +25,6 @@ obj-$(CONFIG_COMEDI_PCM3724)          += pcm3724.o
 obj-$(CONFIG_COMEDI_PCM3730)           += pcm3730.o
 obj-$(CONFIG_COMEDI_RTI800)            += rti800.o
 obj-$(CONFIG_COMEDI_RTI802)            += rti802.o
-obj-$(CONFIG_COMEDI_DAS08)             += das08.o
 obj-$(CONFIG_COMEDI_DAS16M1)           += das16m1.o
 obj-$(CONFIG_COMEDI_DAS16)             += das16.o
 obj-$(CONFIG_COMEDI_DAS800)            += das800.o
@@ -135,4 +133,6 @@ obj-$(CONFIG_COMEDI_NI_TIO)         += ni_tio.o
 obj-$(CONFIG_COMEDI_NI_TIO)            += ni_tiocmd.o
 obj-$(CONFIG_COMEDI_NI_LABPC)          += ni_labpc.o
 
+obj-$(CONFIG_COMEDI_8255)              += 8255.o
+obj-$(CONFIG_COMEDI_DAS08)             += das08.o
 obj-$(CONFIG_COMEDI_FC)                        += comedi_fc.o
index 2c986413a81a442db349d018fa4bf300991ace01..b18e81d8cf8a5187fc4bc41afc974b5eb91ccbae 100644 (file)
@@ -68,6 +68,10 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 #include "addi_common.h"
 #include "addi_amcc_s5933.h"
 
+#ifndef ADDIDATA_DRIVER_NAME
+#define ADDIDATA_DRIVER_NAME   "addi_common"
+#endif
+
 /* Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH <info@addi-data.com>"); */
 /* Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module"); */
 /* Update-0.7.57->0.7.68MODULE_LICENSE("GPL"); */
@@ -2528,7 +2532,7 @@ static const struct addi_board boardtypes[] = {
 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct addi_board))
 
 static struct comedi_driver driver_addi = {
-       .driver_name = "addi_common",
+       .driver_name = ADDIDATA_DRIVER_NAME,
        .module = THIS_MODULE,
        .attach = i_ADDI_Attach,
        .detach = i_ADDI_Detach,
@@ -2570,10 +2574,6 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
        struct pcilst_struct *card = NULL;
        unsigned char pci_bus, pci_slot, pci_func;
        int i_Dma = 0;
-       static char c_Identifier[150];
-
-       sprintf(c_Identifier, "Addi-Data GmbH Comedi %s",
-               this_board->pc_DriverName);
 
        ret = alloc_private(dev, sizeof(struct addi_private));
        if (ret < 0)
@@ -2583,7 +2583,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
                v_pci_card_list_init(this_board->i_VendorId, 1);        /* 1 for displaying the list.. */
                pci_list_builded = 1;
        }
-       /* printk("comedi%d: addi_common: board=%s",dev->minor,this_board->pc_DriverName); */
+       /* printk("comedi%d: "ADDIDATA_DRIVER_NAME": board=%s",dev->minor,this_board->pc_DriverName); */
 
        if ((this_board->i_Dma) && (it->options[2] == 0)) {
                i_Dma = 1;
@@ -2648,7 +2648,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
        if (irq > 0) {
                if (request_irq(irq, v_ADDI_Interrupt, IRQF_SHARED,
-                               c_Identifier, dev) < 0) {
+                               this_board->pc_DriverName, dev) < 0) {
                        printk(", unable to allocate IRQ %u, DISABLING IT",
                                irq);
                        irq = 0;        /* Can't use IRQ */
index da454e854c4cd16e7c02c98271399300e52263dc..6dfcbe803f2dcd18aeec42f93e7ea13861eb7fcd 100644 (file)
@@ -2,4 +2,6 @@
 
 #define ADDIDATA_WATCHDOG 2    /*  Or shold it be something else */
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_035"
+
 #include "addi-data/addi_common.c"
index fa2056e8aa0ece225245701122c1b3bc73423106..4722ec834f7bfd796b42da0c1a2883c4dc4b5993 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_1032 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_1032"
+
 #include "addi-data/addi_common.c"
index 7a5cae599ef80650fc5b8050f63a6dc520641e8d..db3dafdcf691728bb46bb4a653ea51eb54be6d4d 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_1500 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_1500"
+
 #include "addi-data/addi_common.c"
index 8d414844009f6455e23d8af82ccabc2588a0d3db..f591baff6a0b192606dfc810d5574bb401162618 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_1516 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_1516"
+
 #include "addi-data/addi_common.c"
index 0351cdde102623b628cc2a6111014884d51a80e5..6f5c923ac22604750486fb291f64f8cfffb493a1 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_1564 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_1564"
+
 #include "addi-data/addi_common.c"
index 5067990412948e676193b221e0fefc8d7faafa92..1d926add9e6d9606e57e70befcfa0188b1d6ccd6 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_16XX 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_16xx"
+
 #include "addi-data/addi_common.c"
index c433445913dd828bf63eb4499c1e5111c4d6495c..df6ba8ccf56f050b2062f87eca4ff8b27efa6a4f 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_1710 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_1710"
+
 #include "addi-data/addi_common.c"
index 271c47c8cad3c5bb997ae42e03adf6ec20a5047f..7266e412f0a6373109db9b1835be9276d5d4aff8 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_2016 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_2016"
+
 #include "addi-data/addi_common.c"
index 5108ea2a392435835b6a9181d7b9d8f136ac6f19..f67da94119e8c5ff1c027d801b07f05eb834b43d 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_2032 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_2032"
+
 #include "addi-data/addi_common.c"
index e439f835cf4f77a1bae8d8d765c032af72bd5cf2..bc7f7d6535034902dd37d198b6828968c93e833d 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_2200 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_2200"
+
 #include "addi-data/addi_common.c"
index df97c305828b562cf582fbe62b6df6eefca58a62..d86c4209cb90afd168f36e496b5aad875bcba445 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3001 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_3001"
+
 #include "addi-data/addi_common.c"
index 9183125ddde413cbc6d21307caa33a285a5db830..0b22cf10415d3c9a8cc5d8291deb81fbee2902d1 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3120 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_3120"
+
 #include "addi-data/addi_common.c"
index f25a70b3290b4784de5c842f14dbd1b055ab55fd..159313997dcf64fb97c2233cb661ea58cf8b2304 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3200 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_3200"
+
 #include "addi-data/addi_common.c"
index 1ee4778ad45b38a58de4787e3b003d5ce2452602..733c69abc43a57901d27479105a8d0dfde396eba 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3300 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_3300"
+
 #include "addi-data/addi_common.c"
index 1049e20237e8284357048c22befc1a4200b4f9a3..d8a01b154e3585372fdd3fc103cccb25ea32030a 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3501 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_3501"
+
 #include "addi-data/addi_common.c"
index fb9deb7083bdf5998dedd160c3ff033c99860909..942bc9e259a8bdf3f8df7546350618455eaa66eb 100644 (file)
@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3XXX 1
 
+#define ADDIDATA_DRIVER_NAME   "addi_apci_3xxx"
+
 #include "addi-data/addi_common.c"
index 36a254cd44136bba77257078cb7c7501069d3926..39d112b708e3711c6bf78b7ad966ceafcce810fb 100644 (file)
@@ -824,9 +824,12 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
                plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
                                          false, true, true);
 
-               dev_private->scan_delay =
-                   (async_cmd->scan_begin_arg / (async_cmd->convert_arg *
-                                                 async_cmd->chanlist_len)) - 1;
+               if (async_cmd->scan_begin_src == TRIG_TIMER) {
+                       dev_private->scan_delay =
+                               (async_cmd->scan_begin_arg /
+                                (async_cmd->convert_arg *
+                                 async_cmd->chanlist_len)) - 1;
+               }
 
                break;
 
index 40eeecf5347fc73fbe24c12bdd38cf41698bfe14..e424a0c7d34fdfbb4ca8a26fa42f1cc4e5f2b600 100644 (file)
@@ -7,17 +7,17 @@
 */
 /*
 Driver: adv_pci_dio
-Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1736UP,
-             PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754,
-             PCI-1756, PCI-1762
+Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U,
+             PCI-1736UP, PCI-1750, PCI-1751, PCI-1752, PCI-1753/E,
+             PCI-1754, PCI-1756, PCI-1762
 Author: Michal Dobes <dobes@tesnet.cz>
 Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
-  PCI-1734, PCI-1736UP, PCI-1750,
+  PCI-1734, PCI-1735U, PCI-1736UP, PCI-1750,
   PCI-1751, PCI-1752, PCI-1753,
   PCI-1753+PCI-1753E, PCI-1754, PCI-1756,
   PCI-1760, PCI-1762
 Status: untested
-Updated: Mon, 14 Apr 2008 10:43:08 +0100
+Updated: Tue, 04 May 2010 13:00:00 +0000
 
 This driver supports now only insn interface for DI/DO/DIO.
 
@@ -35,6 +35,7 @@ Configuration options:
 
 #include "comedi_pci.h"
 #include "8255.h"
+#include "8253.h"
 
 #undef PCI_DIO_EXTDEBUG                /* if defined, enable extensive debug logging */
 
@@ -49,7 +50,7 @@ Configuration options:
 
 /* hardware types of the cards */
 enum hw_cards_id {
-       TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1736,
+       TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736,
        TYPE_PCI1750,
        TYPE_PCI1751,
        TYPE_PCI1752,
@@ -67,7 +68,10 @@ enum hw_io_access {
 #define MAX_DI_SUBDEVS 2       /* max number of DI subdevices per card */
 #define MAX_DO_SUBDEVS 2       /* max number of DO subdevices per card */
 #define MAX_DIO_SUBDEVG        2       /* max number of DIO subdevices group per card */
+#define MAX_8254_SUBDEVS   1   /* max number of 8254 counter subdevs per card */
+                               /* (could be more than one 8254 per subdevice) */
 
+#define SIZE_8254         4    /* 8254 IO space length */
 #define SIZE_8255         4    /* 8255 IO space length */
 
 #define PCIDIO_MAINREG    2    /* main I/O region for all Advantech cards? */
@@ -85,6 +89,12 @@ enum hw_io_access {
 #define PCI1734_IDO       0    /* W:   Isolated digital output 0-31 */
 #define PCI173x_BOARDID           4    /* R:   Board I/D switch for 1730/3/4 */
 
+/* Advantech PCI-1735U */
+#define PCI1735_DI        0    /* R:   Digital input  0-31 */
+#define PCI1735_DO        0    /* W:   Digital output 0-31 */
+#define PCI1735_C8254     4    /* R/W: 8254 counter */
+#define PCI1735_BOARDID           8    /* R:   Board I/D switch for 1735U */
+
 /*  Advantech PCI-1736UP */
 #define PCI1736_IDI        0   /* R:   Isolated digital input  0-15 */
 #define PCI1736_IDO        0   /* W:   Isolated digital output 0-15 */
@@ -192,7 +202,8 @@ static int pci_dio_detach(struct comedi_device *dev);
 struct diosubd_data {
        int chans;              /*  num of chans */
        int addr;               /*  PCI address ofset */
-       int regs;               /*  number of registers to read or 8255 subdevices */
+       int regs;               /*  number of registers to read or 8255
+                                   subdevices or 8254 chips */
        unsigned int specflags; /*  addon subdevice flags */
 };
 
@@ -206,6 +217,7 @@ struct dio_boardtype {
        struct diosubd_data sdo[MAX_DO_SUBDEVS];        /*  DO chans */
        struct diosubd_data sdio[MAX_DIO_SUBDEVG];      /*  DIO 8255 chans */
        struct diosubd_data boardid;    /*  card supports board ID switch */
+       struct diosubd_data s8254[MAX_8254_SUBDEVS];    /* 8254 subdevices */
        enum hw_io_access io_access;
 };
 
@@ -214,6 +226,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = {
        PCI_VENDOR_ID_ADVANTECH, 0x1730, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
        PCI_VENDOR_ID_ADVANTECH, 0x1733, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
        PCI_VENDOR_ID_ADVANTECH, 0x1734, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
+       PCI_VENDOR_ID_ADVANTECH, 0x1735, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
        PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
        PCI_VENDOR_ID_ADVANTECH, 0x1750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
        PCI_VENDOR_ID_ADVANTECH, 0x1751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
@@ -235,14 +248,15 @@ static const struct dio_boardtype boardtypes[] = {
         {{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}},
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
-        IO_8b,
-        },
+        {{0, 0, 0, 0}},
+        IO_8b},
        {"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
         TYPE_PCI1733,
         {{0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0}},
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
+        {{0, 0, 0, 0}},
         IO_8b},
        {"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
         TYPE_PCI1734,
@@ -250,6 +264,15 @@ static const struct dio_boardtype boardtypes[] = {
         {{0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0}},
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
+        {{0, 0, 0, 0}},
+        IO_8b},
+       {"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
+        TYPE_PCI1735,
+        {{32, PCI1735_DI, 4, 0}, {0, 0, 0, 0}},
+        {{32, PCI1735_DO, 4, 0}, {0, 0, 0, 0}},
+        {{0, 0, 0, 0}, {0, 0, 0, 0}},
+        { 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
+        {{3, PCI1735_C8254, 1, 0}},
         IO_8b},
        {"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
         TYPE_PCI1736,
@@ -257,14 +280,15 @@ static const struct dio_boardtype boardtypes[] = {
         {{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}},
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {4, PCI1736_BOARDID, 1, SDF_INTERNAL},
-        IO_8b,
-        },
+        {{0, 0, 0, 0}},
+        IO_8b},
        {"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
         TYPE_PCI1750,
         {{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}},
         {{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}},
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {0, 0, 0, 0},
+        {{0, 0, 0, 0}},
         IO_8b},
        {"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
         TYPE_PCI1751,
@@ -272,6 +296,7 @@ static const struct dio_boardtype boardtypes[] = {
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {{48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0}},
         {0, 0, 0, 0},
+        {{0, 0, 0, 0}},
         IO_8b},
        {"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
         TYPE_PCI1752,
@@ -279,6 +304,7 @@ static const struct dio_boardtype boardtypes[] = {
         {{32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0}},
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+        {{0, 0, 0, 0}},
         IO_16b},
        {"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
         TYPE_PCI1753,
@@ -286,6 +312,7 @@ static const struct dio_boardtype boardtypes[] = {
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {{96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0}},
         {0, 0, 0, 0},
+        {{0, 0, 0, 0}},
         IO_8b},
        {"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
         TYPE_PCI1753E,
@@ -293,6 +320,7 @@ static const struct dio_boardtype boardtypes[] = {
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {{96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0}},
         {0, 0, 0, 0},
+        {{0, 0, 0, 0}},
         IO_8b},
        {"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
         TYPE_PCI1754,
@@ -300,6 +328,7 @@ static const struct dio_boardtype boardtypes[] = {
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+        {{0, 0, 0, 0}},
         IO_16b},
        {"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
         TYPE_PCI1756,
@@ -307,6 +336,7 @@ static const struct dio_boardtype boardtypes[] = {
         {{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}},
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+        {{0, 0, 0, 0}},
         IO_16b},
        {"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
         TYPE_PCI1760,
@@ -314,6 +344,7 @@ static const struct dio_boardtype boardtypes[] = {
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {0, 0, 0, 0},
+        {{0, 0, 0, 0}},
         IO_8b},
        {"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
         TYPE_PCI1762,
@@ -321,6 +352,7 @@ static const struct dio_boardtype boardtypes[] = {
         {{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}},
         {{0, 0, 0, 0}, {0, 0, 0, 0}},
         {4, PCI1762_BOARDID, 1, SDF_INTERNAL},
+        {{0, 0, 0, 0}},
         IO_16b}
 };
 
@@ -437,6 +469,83 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
        return 2;
 }
 
+/*
+==============================================================================
+*/
+static int pci_8254_insn_read(struct comedi_device *dev,
+                             struct comedi_subdevice *s,
+                             struct comedi_insn *insn, unsigned int *data)
+{
+       const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+       unsigned int chan, chip, chipchan;
+       unsigned long flags;
+
+       chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
+       chip = chan / 3;                /* chip on subdevice */
+       chipchan = chan - (3 * chip);   /* channel on chip on subdevice */
+       spin_lock_irqsave(&s->spin_lock, flags);
+       data[0] = i8254_read(dev->iobase + d->addr + (SIZE_8254 * chip),
+                       0, chipchan);
+       spin_unlock_irqrestore(&s->spin_lock, flags);
+       return 1;
+}
+
+/*
+==============================================================================
+*/
+static int pci_8254_insn_write(struct comedi_device *dev,
+                              struct comedi_subdevice *s,
+                              struct comedi_insn *insn, unsigned int *data)
+{
+       const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+       unsigned int chan, chip, chipchan;
+       unsigned long flags;
+
+       chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
+       chip = chan / 3;                /* chip on subdevice */
+       chipchan = chan - (3 * chip);   /* channel on chip on subdevice */
+       spin_lock_irqsave(&s->spin_lock, flags);
+       i8254_write(dev->iobase + d->addr + (SIZE_8254 * chip),
+                       0, chipchan, data[0]);
+       spin_unlock_irqrestore(&s->spin_lock, flags);
+       return 1;
+}
+
+/*
+==============================================================================
+*/
+static int pci_8254_insn_config(struct comedi_device *dev,
+                               struct comedi_subdevice *s,
+                               struct comedi_insn *insn, unsigned int *data)
+{
+       const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+       unsigned int chan, chip, chipchan;
+       unsigned long iobase;
+       int ret = 0;
+       unsigned long flags;
+
+       chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
+       chip = chan / 3;                /* chip on subdevice */
+       chipchan = chan - (3 * chip);   /* channel on chip on subdevice */
+       iobase = dev->iobase + d->addr + (SIZE_8254 * chip);
+       spin_lock_irqsave(&s->spin_lock, flags);
+       switch (data[0]) {
+       case INSN_CONFIG_SET_COUNTER_MODE:
+               ret = i8254_set_mode(iobase, 0, chipchan, data[1]);
+               if (ret < 0)
+                       ret = -EINVAL;
+               break;
+       case INSN_CONFIG_8254_READ_STATUS:
+               data[1] = i8254_status(iobase, 0, chipchan);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       spin_unlock_irqrestore(&s->spin_lock, flags);
+       return ret < 0 ? ret : insn->n;
+}
+
 /*
 ==============================================================================
 */
@@ -708,6 +817,15 @@ static int pci_dio_reset(struct comedi_device *dev)
                outb(0, dev->iobase + PCI1734_IDO + 2);
                outb(0, dev->iobase + PCI1734_IDO + 3);
                break;
+       case TYPE_PCI1735:
+               outb(0, dev->iobase + PCI1735_DO);      /*  clear outputs */
+               outb(0, dev->iobase + PCI1735_DO + 1);
+               outb(0, dev->iobase + PCI1735_DO + 2);
+               outb(0, dev->iobase + PCI1735_DO + 3);
+               i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 0, I8254_MODE0);
+               i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 1, I8254_MODE0);
+               i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 2, I8254_MODE0);
+               break;
 
        case TYPE_PCI1736:
                outb(0, dev->iobase + PCI1736_IDO);
@@ -874,6 +992,26 @@ static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
        return 0;
 }
 
+/*
+==============================================================================
+*/
+static int pci_dio_add_8254(struct comedi_device *dev,
+                           struct comedi_subdevice * s,
+                           const struct diosubd_data *d, int subdev)
+{
+       s->type = COMEDI_SUBD_COUNTER;
+       s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+       s->n_chan = d->chans;
+       s->maxdata = 65535;
+       s->len_chanlist = d->chans;
+       s->insn_read = pci_8254_insn_read;
+       s->insn_write = pci_8254_insn_write;
+       s->insn_config = pci_8254_insn_config;
+       s->private = (void *)d;
+
+       return 0;
+}
+
 /*
 ==============================================================================
 */
@@ -979,6 +1117,9 @@ static int pci_dio_attach(struct comedi_device *dev,
                        n_subdevices += this_board->sdio[i].regs;
                if (this_board->boardid.chans)
                        n_subdevices++;
+               for (i = 0; i < MAX_8254_SUBDEVS; i++)
+                       if (this_board->s8254[i].chans)
+                               n_subdevices++;
        }
 
        ret = alloc_subdevices(dev, n_subdevices);
@@ -1022,6 +1163,13 @@ static int pci_dio_attach(struct comedi_device *dev,
                subdev++;
        }
 
+       for (i = 0; i < MAX_8254_SUBDEVS; i++)
+               if (this_board->s8254[i].chans) {
+                       s = dev->subdevices + subdev;
+                       pci_dio_add_8254(dev, s, &this_board->s8254[i], subdev);
+                       subdev++;
+               }
+
        if (this_board->cardtype == TYPE_PCI1760)
                pci1760_attach(dev, it);
 
@@ -1067,6 +1215,16 @@ static int pci_dio_detach(struct comedi_device *dev)
                        }
                }
 
+               if (this_board->boardid.chans) {
+                       subdev++;
+               }
+
+               for (i = 0; i < MAX_8254_SUBDEVS; i++) {
+                       if (this_board->s8254[i].chans) {
+                               subdev++;
+                       }
+               }
+
                for (i = 0; i < dev->n_subdevices; i++) {
                        s = dev->subdevices + i;
                        s->private = NULL;
index 8eb67651486aadec3839caa960e14b027dbc55c2..bf27617aa62d426e15cdb93b7436613633ff138e 100644 (file)
@@ -460,6 +460,7 @@ struct dio200_subdev_8254 {
        int has_clk_gat_sce;
        unsigned clock_src[3];  /* Current clock sources */
        unsigned gate_src[3];   /* Current gate sources */
+       spinlock_t spinlock;
 };
 
 struct dio200_subdev_intr {
@@ -1042,8 +1043,11 @@ dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
 {
        struct dio200_subdev_8254 *subpriv = s->private;
        int chan = CR_CHAN(insn->chanspec);
+       unsigned long flags;
 
+       spin_lock_irqsave(&subpriv->spinlock, flags);
        data[0] = i8254_read(subpriv->iobase, 0, chan);
+       spin_unlock_irqrestore(&subpriv->spinlock, flags);
 
        return 1;
 }
@@ -1057,8 +1061,11 @@ dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
 {
        struct dio200_subdev_8254 *subpriv = s->private;
        int chan = CR_CHAN(insn->chanspec);
+       unsigned long flags;
 
+       spin_lock_irqsave(&subpriv->spinlock, flags);
        i8254_write(subpriv->iobase, 0, chan, data[0]);
+       spin_unlock_irqrestore(&subpriv->spinlock, flags);
 
        return 1;
 }
@@ -1151,14 +1158,16 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
                          struct comedi_insn *insn, unsigned int *data)
 {
        struct dio200_subdev_8254 *subpriv = s->private;
-       int ret;
+       int ret = 0;
        int chan = CR_CHAN(insn->chanspec);
+       unsigned long flags;
 
+       spin_lock_irqsave(&subpriv->spinlock, flags);
        switch (data[0]) {
        case INSN_CONFIG_SET_COUNTER_MODE:
                ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
                if (ret < 0)
-                       return -EINVAL;
+                       ret = -EINVAL;
                break;
        case INSN_CONFIG_8254_READ_STATUS:
                data[1] = i8254_status(subpriv->iobase, 0, chan);
@@ -1166,30 +1175,35 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
        case INSN_CONFIG_SET_GATE_SRC:
                ret = dio200_set_gate_src(subpriv, chan, data[2]);
                if (ret < 0)
-                       return -EINVAL;
+                       ret = -EINVAL;
                break;
        case INSN_CONFIG_GET_GATE_SRC:
                ret = dio200_get_gate_src(subpriv, chan);
-               if (ret < 0)
-                       return -EINVAL;
+               if (ret < 0) {
+                       ret = -EINVAL;
+                       break;
+               }
                data[2] = ret;
                break;
        case INSN_CONFIG_SET_CLOCK_SRC:
                ret = dio200_set_clock_src(subpriv, chan, data[1]);
                if (ret < 0)
-                       return -EINVAL;
+                       ret = -EINVAL;
                break;
        case INSN_CONFIG_GET_CLOCK_SRC:
                ret = dio200_get_clock_src(subpriv, chan, &data[2]);
-               if (ret < 0)
-                       return -EINVAL;
+               if (ret < 0) {
+                       ret = -EINVAL;
+                       break;
+               }
                data[1] = ret;
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
                break;
        }
-       return insn->n;
+       spin_unlock_irqrestore(&subpriv->spinlock, flags);
+       return ret < 0 ? ret : insn->n;
 }
 
 /*
@@ -1222,6 +1236,7 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
        s->insn_write = dio200_subdev_8254_write;
        s->insn_config = dio200_subdev_8254_config;
 
+       spin_lock_init(&subpriv->spinlock);
        subpriv->iobase = offset + iobase;
        subpriv->has_clk_gat_sce = has_clk_gat_sce;
        if (has_clk_gat_sce) {
index 81829d6fd2878bb07f2ca53caf2c11f050aee533..c374bee250687597a8c196e8a8823b44f2ea3aaa 100644 (file)
@@ -52,7 +52,6 @@ Please report success/failure with other different cards to
 #include "8255.h"
 
 #define PCI_VENDOR_ID_CB       0x1307  /*  PCI vendor number of ComputerBoards */
-#define N_BOARDS       10      /*  Number of boards in cb_pcidda_boards */
 #define EEPROM_SIZE    128     /*  number of entries in eeprom */
 #define MAX_AO_CHANNELS 8      /*  maximum number of ao channels for supported boards */
 
@@ -307,7 +306,7 @@ static int cb_pcidda_attach(struct comedi_device *dev,
                                        continue;
                                }
                        }
-                       for (index = 0; index < N_BOARDS; index++) {
+                       for (index = 0; index < ARRAY_SIZE(cb_pcidda_boards); index++) {
                                if (cb_pcidda_boards[index].device_id ==
                                    pcidev->device) {
                                        goto found;
index cedb02d40f9515683e852adebaebd26660134e45..3a46f0c0bff905e7df83c80e8a794d67a7a24f53 100644 (file)
@@ -123,7 +123,7 @@ static const struct ni_board_struct ni_boards[] = {
         .adbits = 12,
         .ai_fifo_depth = 1024,
         .alwaysdither = 0,
-        .gainlkup = ai_gain_16,
+        .gainlkup = ai_gain_4,
         .ai_speed = 5000,
         .n_aochan = 2,
         .aobits = 12,
index 86f035d00675067b8d020cbc90ad4b2ca97eaaf5..27b4cb2e2ec2924928b44089c92dc61ee9bab87a 100644 (file)
@@ -351,8 +351,7 @@ static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
        int ret = 0;
 
        if (!this_usbduxsub) {
-               dev_err(&this_usbduxsub->interface->dev,
-                       "comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
+               pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
                return -EFAULT;
        }
        dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n");
index 1f020dad6234b475ea4edc76dd48d7e02278b341..3320359408a966b15d11809ddf9760b00e2a782a 100644 (file)
@@ -519,7 +519,6 @@ err_input_register_device_failed:
 err_input_dev_alloc_failed:
 err_detect_failed:
 err_power_failed:
-       i2c_set_clientdata(client, NULL);
        kfree(ts);
 err_alloc_data_failed:
 err_check_functionality_failed:
@@ -537,7 +536,6 @@ static int synaptics_ts_remove(struct i2c_client *client)
        else
                hrtimer_cancel(&ts->timer);
        input_unregister_device(ts->input_dev);
-       i2c_set_clientdata(client, NULL);
        kfree(ts);
        return 0;
 }
index bd5adbc2a238fbeb2f1b4fa56e9709f651fbcf02..d33947b0378f0a809533f3133d125213c588e43e 100644 (file)
@@ -176,9 +176,7 @@ int allocator_free_dma(unsigned long address)
        prev = ptr; ptr = ptr->next;
 
        if (!ptr) {
-               printk(KERN_ERR ALL_MSG
-                       "free_dma(0x%08lx) but add. not allocated\n",
-                       ptr->address);
+               pr_err(ALL_MSG "free_dma but add. not allocated\n");
                return -EINVAL;
        }
        PDEBUGG("freeing: %08lx (%li) next %08lx\n", ptr->address, ptr->size,
index bd925457f8b710ec8b44a86b7a32dddc22d0abfd..72f5c1f56d195f9c777ba09106b829f1814b9de0 100644 (file)
@@ -289,7 +289,6 @@ static int wis_saa7113_probe(struct i2c_client *client,
        if (write_regs(client, initial_registers) < 0) {
                printk(KERN_ERR
                        "wis-saa7113: error initializing SAA7113\n");
-               i2c_set_clientdata(client, NULL);
                kfree(dec);
                return -ENODEV;
        }
@@ -301,7 +300,6 @@ static int wis_saa7113_remove(struct i2c_client *client)
 {
        struct wis_saa7113 *dec = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(dec);
        return 0;
 }
index b2eb804c1954ceedd9fe7986e319c9425551babf..cd950b61cf70ee1c4d1d883f2949c5677c085368 100644 (file)
@@ -422,7 +422,6 @@ static int wis_saa7115_probe(struct i2c_client *client,
        if (write_regs(client, initial_registers) < 0) {
                printk(KERN_ERR
                        "wis-saa7115: error initializing SAA7115\n");
-               i2c_set_clientdata(client, NULL);
                kfree(dec);
                return -ENODEV;
        }
@@ -434,7 +433,6 @@ static int wis_saa7115_remove(struct i2c_client *client)
 {
        struct wis_saa7115 *dec = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(dec);
        return 0;
 }
index b1013291190f162f6668af96c8593c81b57cb7e9..981c9b311b8b9643befcd08440b1e598354cc5eb 100644 (file)
@@ -684,7 +684,6 @@ static int wis_sony_tuner_remove(struct i2c_client *client)
 {
        struct wis_sony_tuner *t = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(t);
        return 0;
 }
index 315268d130dd61311873a36bd3ae373ed75f3539..ee28a99dc3883620135726feba6034f54632c9ea 100644 (file)
@@ -323,7 +323,6 @@ static int wis_tw2804_remove(struct i2c_client *client)
 {
        struct wis_tw2804 *dec = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(dec);
        return 0;
 }
index 2afea09091b97e020fff05d4438b1b93156e64a7..80d47269b1c01f4054faeb8f2f4514f242e0dc29 100644 (file)
@@ -294,7 +294,6 @@ static int wis_tw9903_probe(struct i2c_client *client,
 
        if (write_regs(client, initial_registers) < 0) {
                printk(KERN_ERR "wis-tw9903: error initializing TW9903\n");
-               i2c_set_clientdata(client, NULL);
                kfree(dec);
                return -ENODEV;
        }
@@ -306,7 +305,6 @@ static int wis_tw9903_remove(struct i2c_client *client)
 {
        struct wis_tw9903 *dec = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(dec);
        return 0;
 }
index 3f53b4d1e4cffcf09552871b30f5c9d6f98ce8a3..12db555a3a5d59b1348c4f3616e246991f7c3246 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/completion.h>
 #include "osd.h"
 #include "logging.h"
 #include "vmbus_private.h"
@@ -293,6 +294,25 @@ void FreeVmbusChannel(struct vmbus_channel *Channel)
                              Channel);
 }
 
+
+DECLARE_COMPLETION(hv_channel_ready);
+
+/*
+ * Count initialized channels, and ensure all channels are ready when hv_vmbus
+ * module loading completes.
+ */
+static void count_hv_channel(void)
+{
+       static int counter;
+       unsigned long flags;
+
+       spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+       if (++counter == MAX_MSG_TYPES)
+               complete(&hv_channel_ready);
+       spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+}
+
+
 /*
  * VmbusChannelProcessOffer - Process the offer by creating a channel/device
  * associated with this offer
@@ -373,22 +393,21 @@ static void VmbusChannelProcessOffer(void *context)
                 * can cleanup properly
                 */
                newChannel->State = CHANNEL_OPEN_STATE;
-               cnt = 0;
 
-               while (cnt != MAX_MSG_TYPES) {
+               /* Open IC channels */
+               for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
                        if (memcmp(&newChannel->OfferMsg.Offer.InterfaceType,
                                   &hv_cb_utils[cnt].data,
-                                  sizeof(struct hv_guid)) == 0) {
+                                  sizeof(struct hv_guid)) == 0 &&
+                               VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
+                                                2 * PAGE_SIZE, NULL, 0,
+                                                hv_cb_utils[cnt].callback,
+                                                newChannel) == 0) {
+                               hv_cb_utils[cnt].channel = newChannel;
                                DPRINT_INFO(VMBUS, "%s",
-                                           hv_cb_utils[cnt].log_msg);
-
-                               if (VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
-                                                   2 * PAGE_SIZE, NULL, 0,
-                                                   hv_cb_utils[cnt].callback,
-                                                   newChannel) == 0)
-                                       hv_cb_utils[cnt].channel = newChannel;
+                                               hv_cb_utils[cnt].log_msg);
+                               count_hv_channel();
                        }
-                       cnt++;
                }
        }
        DPRINT_EXIT(VMBUS);
index 8a49aafea37a5c7a7f2597e53134530c88331f11..2adc9b48ca9cf5aea96de4cc672f62327945af83 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 #include <linux/reboot.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
 
 #include "logging.h"
 #include "osd.h"
@@ -251,10 +253,36 @@ static void heartbeat_onchannelcallback(void *context)
        DPRINT_EXIT(VMBUS);
 }
 
+static const struct pci_device_id __initconst
+hv_utils_pci_table[] __maybe_unused = {
+       { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */
+       { 0 }
+};
+MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
+
+
+static const struct dmi_system_id __initconst
+hv_utils_dmi_table[] __maybe_unused  = {
+       {
+               .ident = "Hyper-V",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+               },
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table);
+
+
 static int __init init_hyperv_utils(void)
 {
        printk(KERN_INFO "Registering HyperV Utility Driver\n");
 
+       if (!dmi_check_system(hv_utils_dmi_table))
+               return -ENODEV;
+
        hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback =
                &shutdown_onchannelcallback;
        hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
index 0c6ee0f487f3538384e0d4f2931b2f496b6a01e8..3c14b2926e0018e1e8ef157df37fc770a6d440b3 100644 (file)
@@ -74,4 +74,6 @@ int vmbus_child_driver_register(struct driver_context *driver_ctx);
 void vmbus_child_driver_unregister(struct driver_context *driver_ctx);
 void vmbus_get_interface(struct vmbus_channel_interface *interface);
 
+extern struct completion hv_channel_ready;
+
 #endif /* _VMBUS_H_ */
index c21731a12ca7a7a8e8a9929369b2f99833c5e2f2..22c80ece6388c5e72661864105f4d35ebf7e1824 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/pci.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <linux/completion.h>
 #include "version_info.h"
 #include "osd.h"
 #include "logging.h"
@@ -356,6 +357,8 @@ static int vmbus_bus_init(int (*drv_init)(struct hv_driver *drv))
 
        vmbus_drv_obj->GetChannelOffers();
 
+       wait_for_completion(&hv_channel_ready);
+
 cleanup:
        DPRINT_EXIT(VMBUS_DRV);
 
index a4555e6f133f0f4cca98924a6085aa8b7f0b6ad0..014f6684faba94f8ba6c28fcd606a131050bfdde 100644 (file)
@@ -62,9 +62,8 @@ inline int find_type_by_name(const char *name, const char *type)
                                        1) != 0) {
                                filename = malloc(strlen(iio_dir)
                                                + strlen(type)
-                                               + 1
                                                + numstrlen
-                                               + 1);
+                                               + 6);
                                if (filename == NULL)
                                        return -ENOMEM;
                                sprintf(filename, "%s%s%d/name",
index 20e267448d1fdffe25eedf5ef35c1b10c2746413..905f8560d31f94d0a4651d54ab8b8191ca69d1f4 100644 (file)
@@ -1011,7 +1011,6 @@ error_put_reg:
        if (!IS_ERR(st->reg))
                regulator_put(st->reg);
 error_free_st:
-       i2c_set_clientdata(client, NULL);
        kfree(st);
 
 error_ret:
@@ -1030,7 +1029,6 @@ static int max1363_remove(struct i2c_client *client)
                regulator_disable(st->reg);
                regulator_put(st->reg);
        }
-       i2c_set_clientdata(client, NULL);
        kfree(st);
 
        return 0;
index 43aaacff4e744bc6a1d18f182f5ac640ac2eabef..e4b0a5ef1c1f4913d39870c9ef363917ca552e83 100644 (file)
@@ -694,7 +694,6 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
 fail2:
        iio_device_unregister(chip->indio_dev);
 fail1:
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return err;
 }
@@ -705,7 +704,6 @@ static int tsl2563_remove(struct i2c_client *client)
 
        iio_device_unregister(chip->indio_dev);
 
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return 0;
 }
index 1f14cd4770e7103515d157e3029f44b516e66276..294272d0619fd0567143392d41bb6dae1babfe30 100644 (file)
@@ -20,7 +20,7 @@ static inline int __iio_allocate_sw_ring_buffer(struct iio_sw_ring_buffer *ring,
        if ((length == 0) || (bytes_per_datum == 0))
                return -EINVAL;
        __iio_update_ring_buffer(&ring->buf, bytes_per_datum, length);
-       ring->data = kmalloc(length*ring->buf.bpd, GFP_KERNEL);
+       ring->data = kmalloc(length*ring->buf.bpd, GFP_ATOMIC);
        ring->read_p = NULL;
        ring->write_p = NULL;
        ring->last_written_p = NULL;
diff --git a/drivers/staging/mrst-touchscreen/Kconfig b/drivers/staging/mrst-touchscreen/Kconfig
new file mode 100644 (file)
index 0000000..c2af492
--- /dev/null
@@ -0,0 +1,7 @@
+config TOUCHSCREEN_INTEL_MID
+       tristate "Intel MID platform resistive touchscreen"
+       depends on INTEL_SCU_IPC
+       default y
+       help
+         Say Y here if you have a Intel MID based touchscreen
+         If unsure, say N.
diff --git a/drivers/staging/mrst-touchscreen/Makefile b/drivers/staging/mrst-touchscreen/Makefile
new file mode 100644 (file)
index 0000000..2d638b0
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) := intel_mid_touch.o
+
+
diff --git a/drivers/staging/mrst-touchscreen/TODO b/drivers/staging/mrst-touchscreen/TODO
new file mode 100644 (file)
index 0000000..7157028
--- /dev/null
@@ -0,0 +1,2 @@
+- Move the driver to not think it is SPI (requires fixing some of the SFI
+  and firmware side)
diff --git a/drivers/staging/mrst-touchscreen/intel-mid-touch.c b/drivers/staging/mrst-touchscreen/intel-mid-touch.c
new file mode 100644 (file)
index 0000000..abba22f
--- /dev/null
@@ -0,0 +1,864 @@
+/*
+ * intel_mid_touch.c - Intel MID Resistive Touch Screen Driver
+ *
+ * Copyright (C) 2008 Intel Corp
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; ifnot, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com)
+ *                         Ramesh Agarwal (ramesh.agarwal@intel.com)
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * TODO:
+ *     kill off mrstouch_debug eventually
+ *     review conversion of r/m/w sequences
+ *     Replace interrupt mutex abuse
+ *     Kill of mrstouchdevp pointer
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/param.h>
+#include <linux/spi/spi.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/intel_scu_ipc.h>
+
+
+#if defined(MRSTOUCH_DEBUG)
+#define mrstouch_debug(fmt, args...)\
+       do { \
+               printk(KERN_DEBUG "\n[MRSTOUCH(%d)] - ", __LINE__); \
+               printk(KERN_DEBUG fmt, ##args); \
+       } while (0);
+#else
+#define mrstouch_debug(fmt, args...)
+#endif
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_ID1   0x00 /*PMIC ID1 register */
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_INT   0x04 /*PMIC interrupt register */
+#define PMIC_REG_MINT  0x05 /*PMIC interrupt mask register */
+
+/* ADC Interrupt registers */
+#define PMIC_REG_ADCINT   0x5F /*ADC interrupt register */
+#define PMIC_REG_MADCINT  0x60 /*ADC interrupt mask register */
+
+/* ADC Control registers */
+#define PMIC_REG_ADCCNTL1    0x61 /*ADC control register */
+
+/* ADC Channel Selection registers */
+#define PMICADDR0     0xA4
+#define END_OF_CHANNEL 0x1F
+
+/* ADC Result register */
+#define PMIC_REG_ADCSNS0H   0x64
+
+/* ADC channels for touch screen */
+#define MRST_TS_CHAN10   0xA /* Touch screen X+ connection */
+#define MRST_TS_CHAN11   0xB /* Touch screen X- connection */
+#define MRST_TS_CHAN12   0xC /* Touch screen Y+ connection */
+#define MRST_TS_CHAN13   0xD /* Touch screen Y- connection */
+
+/* Touch screen coordinate constants */
+#define TOUCH_PRESSURE         50
+#define TOUCH_PRESSURE_FS      100
+
+#define XMOVE_LIMIT    5
+#define YMOVE_LIMIT    5
+#define XYMOVE_CNT     3
+
+#define MAX_10BIT      ((1<<10)-1)
+
+/* Touch screen channel BIAS constants */
+#define XBIAS          0x20
+#define YBIAS          0x40
+#define ZBIAS          0x80
+
+/* Touch screen coordinates */
+#define MIN_X          10
+#define MAX_X          1024
+#define MIN_Y          10
+#define MAX_Y          1024
+#define WAIT_ADC_COMPLETION 10
+
+/* PMIC ADC round robin delays */
+#define ADC_LOOP_DELAY0 0x0 /* Continuous loop */
+#define ADC_LOOP_DELAY1 0x1 /* 4.5  ms approximate */
+
+/* PMIC Vendor Identifiers */
+#define PMIC_VENDOR_FS  0 /* PMIC vendor FreeScale */
+#define PMIC_VENDOR_MAXIM 1 /* PMIC vendor MAXIM */
+#define PMIC_VENDOR_NEC 2 /* PMIC vendor NEC */
+#define MRSTOUCH_MAX_CHANNELS 32 /* Maximum ADC channels */
+
+/* Touch screen device structure */
+struct mrstouch_dev {
+       struct spi_device *spi; /* SPI device associated with touch screen */
+       struct input_dev *input; /* input device for touchscreen*/
+       char            phys[32]; /* Device name */
+       struct task_struct *pendet_thrd; /* PENDET interrupt handler */
+       struct mutex lock; /* Sync between interrupt and PENDET handler */
+       bool            busy; /* Busy flag */
+       u16             asr; /* Address selection register */
+       int             irq;    /* Touch screen IRQ # */
+       uint            vendor;  /* PMIC vendor */
+       uint            rev;  /* PMIC revision */
+       bool            suspended; /* Device suspended status */
+       bool            disabled;  /* Device disabled status */
+       u16             x;  /* X coordinate */
+       u16             y;  /* Y coordinate */
+       bool            pendown;  /* PEN position */
+} ;
+
+
+/* Global Pointer to Touch screen device */
+static struct mrstouch_dev *mrstouchdevp;
+
+/* Utility to read PMIC ID */
+static int mrstouch_pmic_id(uint *vendor, uint *rev)
+{
+       int err;
+       u8 r;
+
+       err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r);
+       if (err)
+               return err;
+
+       *vendor = r & 0x7;
+       *rev = (r >> 3) & 0x7;
+
+       return 0;
+}
+
+/*
+ * Parse ADC channels to find end of the channel configured by other ADC user
+ * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
+ */
+static int mrstouch_chan_parse(struct mrstouch_dev *tsdev)
+{
+       int err, i, j, found;
+       u32 r32;
+
+       found = -1;
+
+       for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
+               if (found >= 0)
+                       break;
+
+               err = intel_scu_ipc_ioread32(PMICADDR0, &r32);
+               if (err)
+                       return err;
+
+               for (j = 0; j < 32; j+= 8) {
+                       if (((r32 >> j) & 0xFF) == END_OF_CHANNEL) {
+                               found = i;
+                               break;
+                       }
+               }
+       }
+       if (found < 0)
+               return 0;
+
+       if (tsdev->vendor == PMIC_VENDOR_FS) {
+               if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
+                       return -ENOSPC;
+       } else {
+               if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
+                       return -ENOSPC;
+       }
+       return found;
+}
+
+/* Utility to enable/disable pendet.
+ * pendet set to true enables PENDET interrupt
+ * pendet set to false disables PENDET interrupt
+ * Also clears RND mask bit
+*/
+static int pendet_enable(struct mrstouch_dev *tsdev, bool pendet)
+{
+       u16 reg;
+       u8 r;
+       u8 pendet_enabled = 0;
+       int retry = 0;
+       int err;
+
+       err = intel_scu_ipc_ioread16(PMIC_REG_MADCINT, &reg);
+       if (err)
+               return err;
+
+       if (pendet) {
+               reg &= ~0x0005;
+               reg |= 0x2000; /* Enable pendet */
+       } else
+               reg &= 0xDFFF; /* Disable pendet */
+
+       /* Set MADCINT and update ADCCNTL1 (next reg byte) */
+       err = intel_scu_ipc_iowrite16(PMIC_REG_MADCINT, reg);
+       if (!pendet || err)
+               return err;
+
+       /*
+        * Sometimes even after the register write succeeds
+        * the PMIC register value is not updated. Retry few iterations
+        * to enable pendet.
+        */
+
+       err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
+       pendet_enabled = (r >> 5) & 0x01;
+
+       retry = 0;
+       while (!err && !pendet_enabled) {
+               retry++;
+               msleep(10);
+               err = intel_scu_ipc_iowrite8(PMIC_REG_ADCCNTL1, reg >> 8);
+               if (err)
+                       break;
+               err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
+               if (err == 0)
+                       pendet_enabled = (r >> 5) & 0x01;
+               if (retry >= 10) {
+                       dev_err(&tsdev->spi->dev, "Touch screen disabled.\n");
+                       return -EIO;
+               }
+       }
+       return 0;
+}
+
+/* To read PMIC ADC touch screen result
+ * Reads ADC storage registers for higher 7 and lower 3 bits
+ * converts the two readings to single value and turns off gain bit
+ */
+static int mrstouch_ts_chan_read(u16 offset, u16 chan, u16 *vp, u16 *vm)
+{
+       int err;
+       u16 result;
+       u32 res;
+
+       result = PMIC_REG_ADCSNS0H + offset;
+
+       if (chan == MRST_TS_CHAN12)
+               result += 4;
+
+       err = intel_scu_ipc_ioread32(result, &res);
+       if (err)
+               return err;
+
+       /* Mash the bits up */
+
+       *vp = (res & 0xFF) << 3;        /* Highest 7 bits */
+       *vp |= (res >> 8) & 0x07;       /* Lower 3 bits */
+       *vp &= 0x3FF;
+
+       res >>= 16;
+
+       *vm = (res & 0xFF) << 3;        /* Highest 7 bits */
+       *vm |= (res >> 8) & 0x07;       /* Lower 3 bits */
+       *vm &= 0x3FF;
+
+       return 0;
+}
+
+/* To configure touch screen channels
+ * Writes touch screen channels to ADC address selection registers
+ */
+static int mrstouch_ts_chan_set(uint offset)
+{
+       int count;
+       u16 chan;
+       u16 reg[5];
+       u8 data[5];
+
+       chan = PMICADDR0 + offset;
+       for (count = 0; count <= 3; count++) {
+               reg[count] = chan++;
+               data[count] = MRST_TS_CHAN10 + count;
+       }
+       reg[count] = chan;
+       data[count] = END_OF_CHANNEL;
+
+       return intel_scu_ipc_writev(reg, data, 5);
+}
+
+/* Initialize ADC */
+static int mrstouch_adc_init(struct mrstouch_dev *tsdev)
+{
+       int err, start;
+       u8 ra, rm;
+
+       err = mrstouch_pmic_id(&tsdev->vendor, &tsdev->rev);
+       if (err) {
+               dev_err(&tsdev->spi->dev, "Unable to read PMIC id\n");
+               return err;
+       }
+
+       start = mrstouch_chan_parse(tsdev);
+       if (start < 0) {
+               dev_err(&tsdev->spi->dev, "Unable to parse channels\n");
+               return start;
+       }
+
+       tsdev->asr = start;
+
+       mrstouch_debug("Channel offset(%d): 0x%X\n", tsdev->asr, tsdev->vendor);
+
+       /* ADC power on, start, enable PENDET and set loop delay
+        * ADC loop delay is set to 4.5 ms approximately
+        * Loop delay more than this results in jitter in adc readings
+        * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
+        * interrupt generation sometimes.
+        */
+
+       if (tsdev->vendor == PMIC_VENDOR_FS) {
+               ra = 0xE0 | ADC_LOOP_DELAY0;
+               rm = 0x5;
+       } else {
+               /* NEC and MAXIm not consistent with loop delay 0 */
+               ra = 0xE0 | ADC_LOOP_DELAY1;
+               rm = 0x0;
+
+               /* configure touch screen channels */
+               err = mrstouch_ts_chan_set(tsdev->asr);
+               if (err)
+                       return err;
+       }
+       err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, ra, 0xE7);
+       if (err == 0)
+               err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, rm, 0x03);
+       return err;
+}
+
+/* Reports x,y coordinates to event subsystem */
+static void mrstouch_report_xy(struct mrstouch_dev *tsdev, u16 x, u16 y, u16 z)
+{
+       int xdiff, ydiff;
+
+       if (tsdev->pendown && z <= TOUCH_PRESSURE) {
+               /* Pen removed, report button release */
+               mrstouch_debug("BTN REL(%d)", z);
+               input_report_key(tsdev->input, BTN_TOUCH, 0);
+               tsdev->pendown = false;
+       }
+
+       xdiff = abs(x - tsdev->x);
+       ydiff = abs(y - tsdev->y);
+
+       /*
+       if x and y values changes for XYMOVE_CNT readings it is considered
+       as stylus is moving. This is required to differentiate between stylus
+       movement and jitter
+       */
+       if (x < MIN_X || x > MAX_X || y < MIN_Y || y > MAX_Y) {
+               /* Spurious values, release button if touched and return */
+               if (tsdev->pendown) {
+                       mrstouch_debug("BTN REL(%d)", z);
+                       input_report_key(tsdev->input, BTN_TOUCH, 0);
+                       tsdev->pendown = false;
+               }
+               return;
+       } else if (xdiff >= XMOVE_LIMIT || ydiff >= YMOVE_LIMIT) {
+               tsdev->x = x;
+               tsdev->y = y;
+
+               input_report_abs(tsdev->input, ABS_X, x);
+               input_report_abs(tsdev->input, ABS_Y, y);
+               input_sync(tsdev->input);
+       }
+
+
+       if (!tsdev->pendown && z > TOUCH_PRESSURE) {
+               /* Pen touched, report button touch */
+               mrstouch_debug("BTN TCH(%d, %d, %d)", x, y, z);
+               input_report_key(tsdev->input, BTN_TOUCH, 1);
+               tsdev->pendown = true;
+       }
+}
+
+
+/* Utility to start ADC, used by freescale handler */
+static int pendet_mask(void)
+{
+       return  intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x02, 0x02);
+}
+
+/* Utility to stop ADC, used by freescale handler */
+static int pendet_umask(void)
+{
+       return  intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x00, 0x02);
+}
+
+/* Utility to read ADC, used by freescale handler */
+static int mrstouch_pmic_fs_adc_read(struct mrstouch_dev *tsdev)
+{
+       int err;
+       u16 x, y, z, result;
+       u16 reg[4];
+       u8 data[4];
+
+       result = PMIC_REG_ADCSNS0H + tsdev->asr;
+
+       reg[0] = result + 4;
+       reg[1] = result + 5;
+       reg[2] = result + 16;
+       reg[3] = result + 17;
+
+       err = intel_scu_ipc_readv(reg, data, 4);
+       if (err)
+               goto ipc_error;
+
+       x = data[0] << 3; /* Higher 7 bits */
+       x |= data[1] & 0x7; /* Lower 3 bits */
+       x &= 0x3FF;
+
+       y = data[2] << 3; /* Higher 7 bits */
+       y |= data[3] & 0x7; /* Lower 3 bits */
+       y &= 0x3FF;
+
+       /* Read Z value */
+       reg[0] = result + 28;
+       reg[1] = result + 29;
+
+       err = intel_scu_ipc_readv(reg, data, 4);
+       if (err)
+               goto ipc_error;
+
+       z = data[0] << 3; /* Higher 7 bits */
+       z |= data[1] & 0x7; /* Lower 3 bits */
+       z &= 0x3FF;
+
+#if defined(MRSTOUCH_PRINT_XYZP)
+       mrstouch_debug("X: %d, Y: %d, Z: %d", x, y, z);
+#endif
+
+       if (z >= TOUCH_PRESSURE_FS) {
+               mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE - 1); /* Pen Removed */
+               return TOUCH_PRESSURE - 1;
+       } else {
+               mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE + 1); /* Pen Touched */
+               return TOUCH_PRESSURE + 1;
+       }
+
+       return 0;
+
+ipc_error:
+       dev_err(&tsdev->spi->dev, "ipc error during fs_adc read\n");
+       return err;
+}
+
+/* To handle free scale pmic pendet interrupt */
+static int pmic0_pendet(void *dev_id)
+{
+       int err, count;
+       u16 chan;
+       unsigned int touched;
+       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)dev_id;
+       u16 reg[5];
+       u8 data[5];
+
+       chan = PMICADDR0 + tsdev->asr;
+
+       /* Set X BIAS */
+       for (count = 0; count <= 3; count++) {
+               reg[count] = chan++;
+               data[count] = 0x2A;
+       }
+       reg[count] =  chan++; /* Dummy */
+       data[count] = 0;
+
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* Set Y BIAS */
+       for (count = 0; count <= 3; count++) {
+               reg[count] = chan++;
+               data[count] = 0x4A;
+       }
+       reg[count] = chan++; /* Dummy */
+       data[count] = 0;
+
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* Set Z BIAS */
+       err = intel_scu_ipc_iowrite32(chan + 2, 0x8A8A8A8A);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /*Read touch screen channels till pen removed
+        * Freescale reports constant value of z for all points
+        * z is high when screen is not touched and low when touched
+        * Map high z value to not touched and low z value to pen touched
+        */
+       touched = mrstouch_pmic_fs_adc_read(tsdev);
+       while (touched > TOUCH_PRESSURE) {
+               touched = mrstouch_pmic_fs_adc_read(tsdev);
+               msleep(WAIT_ADC_COMPLETION);
+       }
+
+       /* Clear all TS channels */
+       chan = PMICADDR0 + tsdev->asr;
+       for (count = 0; count <= 4; count++) {
+               reg[count] = chan++;
+               data[count] = 0;
+       }
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       for (count = 0; count <= 4; count++) {
+               reg[count] = chan++;
+               data[count] = 0;
+       }
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       err = intel_scu_ipc_iowrite32(chan + 2, 0x00000000);
+       if (err)
+               goto ipc_error;
+
+       return 0;
+
+ipc_error:
+       dev_err(&tsdev->spi->dev, "ipc error during pendet\n");
+       return err;
+}
+
+
+/* To enable X, Y and Z bias values
+ * Enables YPYM for X channels and XPXM for Y channels
+ */
+static int mrstouch_ts_bias_set(uint offset, uint bias)
+{
+       int count;
+       u16 chan, start;
+       u16 reg[4];
+       u8 data[4];
+
+       chan = PMICADDR0 + offset;
+       start = MRST_TS_CHAN10;
+
+       for (count = 0; count <= 3; count++) {
+               reg[count] = chan++;
+               data[count] = bias | (start + count);
+       }
+       return intel_scu_ipc_writev(reg, data, 4);
+}
+
+/* To read touch screen channel values */
+static int mrstouch_adc_read(struct mrstouch_dev *tsdev)
+{
+       int err;
+       u16 xp, xm, yp, ym, zp, zm;
+
+       /* configure Y bias for X channels */
+       err = mrstouch_ts_bias_set(tsdev->asr, YBIAS);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* read x+ and x- channels */
+       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &xp, &xm);
+       if (err)
+               goto ipc_error;
+
+       /* configure x bias for y channels */
+       err = mrstouch_ts_bias_set(tsdev->asr, XBIAS);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* read y+ and y- channels */
+       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN12, &yp, &ym);
+       if (err)
+               goto ipc_error;
+
+       /* configure z bias for x and y channels */
+       err = mrstouch_ts_bias_set(tsdev->asr, ZBIAS);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* read z+ and z- channels */
+       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &zp, &zm);
+       if (err)
+               goto ipc_error;
+
+#if defined(MRSTOUCH_PRINT_XYZP)
+       printk(KERN_INFO "X+: %d, Y+: %d, Z+: %d\n", xp, yp, zp);
+#endif
+
+#if defined(MRSTOUCH_PRINT_XYZM)
+       printk(KERN_INFO "X-: %d, Y-: %d, Z-: %d\n", xm, ym, zm);
+#endif
+
+       mrstouch_report_xy(tsdev, xp, yp, zp); /* report x and y to eventX */
+
+       return zp;
+
+ipc_error:
+       dev_err(&tsdev->spi->dev, "ipc error during adc read\n");
+       return err;
+}
+
+/* PENDET interrupt handler function for NEC and MAXIM */
+static void pmic12_pendet(void *data)
+{
+       unsigned int touched;
+       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
+
+       /* read touch screen channels till pen removed */
+       do {
+               touched = mrstouch_adc_read(tsdev);
+       } while (touched > TOUCH_PRESSURE);
+}
+
+/* Handler to process PENDET interrupt */
+int mrstouch_pendet(void *data)
+{
+       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
+       while (1) {
+               /* Wait for PENDET interrupt */
+               if (mutex_lock_interruptible(&tsdev->lock)) {
+                       msleep(WAIT_ADC_COMPLETION);
+                       continue;
+               }
+
+               if (tsdev->busy)
+                       return 0;
+
+               tsdev->busy = true;
+
+               if (tsdev->vendor == PMIC_VENDOR_NEC ||
+                       tsdev->vendor == PMIC_VENDOR_MAXIM) {
+                       /* PENDET must be disabled in NEC before reading ADC */
+                       pendet_enable(tsdev,false); /* Disbale PENDET */
+                       pmic12_pendet(tsdev);
+                       pendet_enable(tsdev, true); /*Enable PENDET */
+               } else if (tsdev->vendor == PMIC_VENDOR_FS) {
+                       pendet_umask(); /* Stop ADC */
+                       pmic0_pendet(tsdev);
+                       pendet_mask(); /* Stop ADC */
+               } else
+               dev_err(&tsdev->spi->dev, "Unsupported touchscreen: %d\n",
+                               tsdev->vendor);
+
+               tsdev->busy = false;
+
+       }
+       return 0;
+}
+
+/* PENDET interrupt handler */
+static irqreturn_t pendet_intr_handler(int irq, void *handle)
+{
+       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)handle;
+
+       mutex_unlock(&tsdev->lock);
+       return IRQ_HANDLED;
+}
+
+/* Intializes input device and registers with input subsystem */
+static int ts_input_dev_init(struct mrstouch_dev *tsdev, struct spi_device *spi)
+{
+       int err = 0;
+
+       mrstouch_debug("%s", __func__);
+
+       tsdev->input = input_allocate_device();
+       if (!tsdev->input) {
+               dev_err(&tsdev->spi->dev, "Unable to allocate input device.\n");
+               return -EINVAL;
+       }
+
+       tsdev->input->name = "mrst_touchscreen";
+       snprintf(tsdev->phys, sizeof(tsdev->phys),
+                       "%s/input0", dev_name(&spi->dev));
+       tsdev->input->phys = tsdev->phys;
+       tsdev->input->dev.parent = &spi->dev;
+
+       tsdev->input->id.vendor = tsdev->vendor;
+       tsdev->input->id.version = tsdev->rev;
+
+       tsdev->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       tsdev->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+       input_set_abs_params(tsdev->input, ABS_X, MIN_X, MIN_Y, 0, 0);
+       input_set_abs_params(tsdev->input, ABS_Y, MIN_X, MIN_Y, 0, 0);
+
+       err = input_register_device(tsdev->input);
+       if (err) {
+               dev_err(&tsdev->spi->dev, "unable to register input device\n");
+               input_free_device(tsdev->input);
+               return err;
+       }
+
+       mrstouch_debug("%s", "mrstouch initialized");
+
+       return 0;
+
+}
+
+/* Probe function for touch screen driver */
+static int __devinit mrstouch_probe(struct spi_device *mrstouch_spi)
+{
+       int err;
+       unsigned int myirq;
+       struct mrstouch_dev *tsdev;
+
+       mrstouch_debug("%s(%p)", __func__, mrstouch_spi);
+
+       mrstouchdevp = NULL;
+       myirq = mrstouch_spi->irq;
+
+       if (!mrstouch_spi->irq) {
+               dev_err(&mrstouch_spi->dev, "no interrupt assigned\n");
+               return -EINVAL;
+       }
+
+       tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL);
+       if (!tsdev) {
+               dev_err(&mrstouch_spi->dev, "unable to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       tsdev->irq = myirq;
+       mrstouchdevp = tsdev;
+
+       err = mrstouch_adc_init(tsdev);
+       if (err) {
+               dev_err(&mrstouch_spi->dev, "ADC init failed\n");
+               goto mrstouch_err_free_mem;
+       }
+
+       dev_set_drvdata(&mrstouch_spi->dev, tsdev);
+       tsdev->spi = mrstouch_spi;
+
+       err = ts_input_dev_init(tsdev, mrstouch_spi);
+       if (err) {
+               dev_err(&tsdev->spi->dev, "ts_input_dev_init failed");
+               goto mrstouch_err_free_mem;
+       }
+
+       mutex_init(&tsdev->lock);
+       mutex_lock(&tsdev->lock)
+
+       mrstouch_debug("Requesting IRQ-%d", myirq);
+       err = request_irq(myirq, pendet_intr_handler,
+                               0, "mrstouch", tsdev);
+       if (err) {
+               dev_err(&tsdev->spi->dev, "unable to allocate irq\n");
+               goto mrstouch_err_free_mem;
+       }
+
+       tsdev->pendet_thrd = kthread_run(mrstouch_pendet,
+                               (void *)tsdev, "pendet handler");
+       if (IS_ERR(tsdev->pendet_thrd)) {
+               dev_err(&tsdev->spi->dev, "kthread_run failed\n");
+               err = PTR_ERR(tsdev->pendet_thrd);
+               goto mrstouch_err_free_mem;
+       }
+       mrstouch_debug("%s", "Driver initialized");
+       return 0;
+
+mrstouch_err_free_mem:
+       kfree(tsdev);
+       return err;
+}
+
+static int mrstouch_suspend(struct spi_device *spi, pm_message_t msg)
+{
+       mrstouch_debug("%s", __func__);
+       mrstouchdevp->suspended = 1;
+       return 0;
+}
+
+static int mrstouch_resume(struct spi_device *spi)
+{
+       mrstouch_debug("%s", __func__);
+       mrstouchdevp->suspended = 0;
+       return 0;
+}
+
+static int mrstouch_remove(struct spi_device *spi)
+{
+       mrstouch_debug("%s", __func__);
+       free_irq(mrstouchdevp->irq, mrstouchdevp);
+       input_unregister_device(mrstouchdevp->input);
+       input_free_device(mrstouchdevp->input);
+       if (mrstouchdevp->pendet_thrd)
+               kthread_stop(mrstouchdevp->pendet_thrd);
+       kfree(mrstouchdevp);
+       return 0;
+}
+
+static struct spi_driver mrstouch_driver = {
+       .driver = {
+               .name   = "pmic_touch",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = mrstouch_probe,
+       .suspend        = mrstouch_suspend,
+       .resume         = mrstouch_resume,
+       .remove         = mrstouch_remove,
+};
+
+static int __init mrstouch_module_init(void)
+{
+       int err;
+
+       mrstouch_debug("%s", __func__);
+       err = spi_register_driver(&mrstouch_driver);
+       if (err) {
+               mrstouch_debug("%s(%d)", "SPI PENDET failed", err);
+               return -1;
+       }
+
+       return 0;
+}
+
+static void __exit mrstouch_module_exit(void)
+{
+       mrstouch_debug("%s", __func__);
+       spi_unregister_driver(&mrstouch_driver);
+       return;
+}
+
+module_init(mrstouch_module_init);
+module_exit(mrstouch_module_exit);
+
+MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com");
+MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/msm/Kconfig b/drivers/staging/msm/Kconfig
new file mode 100644 (file)
index 0000000..c57039f
--- /dev/null
@@ -0,0 +1,134 @@
+config MSM_STAGING
+       tristate "MSM Frame Buffer Support"
+       depends on FB && ARCH_MSM && !FB_MSM
+       select FB_BACKLIGHT if FB_MSM_BACKLIGHT
+       select NEW_LEDS
+       select LEDS_CLASS
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       ---help---
+         Support for MSM Framebuffer.
+
+if MSM_STAGING
+
+config FB_MSM_LCDC_HW
+       bool
+       default n
+
+choice
+       prompt "MDP HW version"
+       default FB_MSM_MDP31
+
+config FB_MSM_MDP31
+       select FB_MSM_LCDC_HW
+       bool "MDP HW ver3.1"
+       ---help---
+         Support for MSM MDP HW revision 3.1
+         Say Y here if this is msm8x50 variant platform.
+endchoice
+
+config FB_MSM_LCDC
+       bool
+       default n
+
+config FB_MSM_TVOUT
+       bool
+       default n
+
+config FB_MSM_LCDC_PANEL
+       bool
+       select FB_MSM_LCDC
+       default n
+
+config FB_MSM_LCDC_PRISM_WVGA
+        bool
+       select FB_MSM_LCDC_PANEL
+       default n
+
+config FB_MSM_LCDC_ST1_WXGA
+       bool
+       select FB_MSM_LCDC_PANEL
+       default n
+
+config FB_MSM_LCDC_ST15_WXGA
+        bool
+        select FB_MSM_LCDC_PANEL
+        default n
+
+config FB_MSM_LCDC_WXGA
+       bool
+       select FB_MSM_LCDC_PANEL
+       default n
+
+choice
+       prompt "LCD Panel"
+       default FB_MSM_LCDC_ST15_PANEL
+
+config FB_MSM_LCDC_PRISM_WVGA_PANEL
+       depends on FB_MSM_LCDC_HW
+       bool "LCDC Prism WVGA Panel"
+       select FB_MSM_LCDC_PRISM_WVGA
+       ---help---
+         Support for LCDC Prism WVGA (800x480) panel
+
+
+config FB_MSM_LCDC_ST15_PANEL
+        depends on FB_MSM_LCDC_HW
+        bool "LCDC ST1.5 Panel"
+        select FB_MSM_LCDC_ST15_WXGA
+        ---help---
+          Support for ST1.5 WXGA (1366x768) panel
+
+config FB_MSM_PANEL_NONE
+       bool "NONE"
+       ---help---
+         This will disable LCD panel
+endchoice
+
+choice
+       prompt "Secondary LCD Panel"
+       depends on  FB_MSM_MDP31
+       default FB_MSM_SECONDARY_PANEL_NONE
+
+config FB_MSM_SECONDARY_PANEL_NONE
+       bool "NONE"
+       ---help---
+         No secondary panel
+endchoice
+
+config FB_MSM_TVOUT_NTSC
+       bool
+       select FB_MSM_TVOUT
+       default n
+
+config FB_MSM_TVOUT_PAL
+       bool
+       select FB_MSM_TVOUT
+       default n
+
+choice
+       depends on  (FB_MSM_MDP22 || FB_MSM_MDP31)
+       prompt "TVOut Region"
+       default FB_MSM_TVOUT_NTSC_M
+
+config FB_MSM_TVOUT_NTSC_M
+       bool "NTSC M"
+       select FB_MSM_TVOUT_NTSC
+       ---help---
+         Support for NTSC M region (North American and Korea)
+
+config FB_MSM_TVOUT_NONE
+       bool "NONE"
+       ---help---
+         This will disable TV Out functionality.
+endchoice
+
+config PMEM_KERNEL_SIZE
+        int "PMEM for kernel components (in MB)"
+        default 2
+        depends on ARCH_QSD8X50
+        help
+          Configures the amount of PMEM for use by kernel components
+          (in MB; minimum 2MB)
+endif
diff --git a/drivers/staging/msm/Makefile b/drivers/staging/msm/Makefile
new file mode 100644 (file)
index 0000000..98a0ce1
--- /dev/null
@@ -0,0 +1,93 @@
+obj-y := msm_fb.o staging-devices.o memory.o
+
+obj-$(CONFIG_FB_MSM_LOGO) += logo.o
+obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
+
+# MDP
+obj-y += mdp.o
+
+ifeq ($(CONFIG_FB_MSM_MDP40),y)
+obj-y += mdp4_util.o
+obj-$(CONFIG_DEBUG_FS) += mdp4_debugfs.o
+else
+obj-y += mdp_hw_init.o
+obj-y += mdp_ppp.o
+ifeq ($(CONFIG_FB_MSM_MDP31),y)
+obj-y += mdp_ppp_v31.o
+obj-$(CONFIG_MDP_PPP_ASYNC_OP) += mdp_ppp_dq.o
+else
+obj-y += mdp_ppp_v20.o
+endif
+endif
+
+ifeq ($(CONFIG_FB_MSM_OVERLAY),y)
+obj-y += mdp4_overlay.o
+obj-y += mdp4_overlay_lcdc.o
+obj-y += mdp4_overlay_mddi.o
+else
+obj-y += mdp_dma_lcdc.o
+endif
+
+obj-y += mdp_dma.o
+obj-y += mdp_dma_s.o
+obj-y += mdp_vsync.o
+obj-y += mdp_cursor.o
+obj-y += mdp_dma_tv.o
+
+# EBI2
+obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
+
+# LCDC
+obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o
+
+# MDDI
+msm_mddi-objs := mddi.o mddihost.o mddihosti.o
+obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o
+
+# External MDDI
+msm_mddi_ext-objs := mddihost_e.o mddi_ext.o
+obj-$(CONFIG_FB_MSM_EXTMDDI) += msm_mddi_ext.o
+
+# TVEnc
+obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o
+
+# MSM FB Panel
+obj-y += msm_fb_panel.o
+obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_tmd20.o
+obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_l2f.o
+
+ifeq ($(CONFIG_FB_MSM_MDDI_AUTO_DETECT),y)
+obj-y += mddi_prism.o
+obj-y += mddi_toshiba.o
+obj-y += mddi_toshiba_vga.o
+obj-y += mddi_toshiba_wvga_pt.o
+obj-y += mddi_toshiba_wvga.o
+obj-y += mddi_sharp.o
+else
+obj-$(CONFIG_FB_MSM_MDDI_PRISM_WVGA) += mddi_prism.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON) += mddi_toshiba.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA) += mddi_toshiba_vga.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA_PORTRAIT) += mddi_toshiba_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA) += mddi_toshiba_wvga.o
+obj-$(CONFIG_FB_MSM_MDDI_SHARP_QVGA_128x128) += mddi_sharp.o
+endif
+
+obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o
+obj-$(CONFIG_FB_MSM_LCDC_PRISM_WVGA) += lcdc_prism.o
+obj-$(CONFIG_FB_MSM_LCDC_EXTERNAL_WXGA) += lcdc_external.o
+obj-$(CONFIG_FB_MSM_LCDC_GORDON_VGA) += lcdc_gordon.o
+obj-$(CONFIG_FB_MSM_LCDC_WXGA) += lcdc_wxga.o
+obj-$(CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT) += lcdc_toshiba_wvga_pt.o
+obj-$(CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT) += lcdc_sharp_wvga_pt.o
+obj-$(CONFIG_FB_MSM_LCDC_GRAPEFRUIT_VGA) += lcdc_grapefruit.o
+obj-$(CONFIG_FB_MSM_LCDC_ST1_WXGA) += lcdc_st1_wxga.o
+obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o
+obj-$(CONFIG_FB_MSM_HDMI_SII_EXTERNAL_720P) += hdmi_sii9022.o
+
+obj-$(CONFIG_FB_MSM_TVOUT_NTSC) += tv_ntsc.o
+obj-$(CONFIG_FB_MSM_TVOUT_PAL) += tv_pal.o
+
+obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o
+
+clean:
+       rm *.o .*cmd
diff --git a/drivers/staging/msm/TODO b/drivers/staging/msm/TODO
new file mode 100644 (file)
index 0000000..05107a7
--- /dev/null
@@ -0,0 +1,3 @@
+- Merge this code with the existing MSM framebuffer
+- General style clean ups.
+
diff --git a/drivers/staging/msm/ebi2_l2f.c b/drivers/staging/msm/ebi2_l2f.c
new file mode 100644 (file)
index 0000000..eea891d
--- /dev/null
@@ -0,0 +1,569 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#include <linux/memory.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+/* The following are for MSM5100 on Gator
+*/
+#ifdef FEATURE_PM1000
+#include "pm1000.h"
+#endif /* FEATURE_PM1000 */
+/* The following are for MSM6050 on Bambi
+*/
+#ifdef FEATURE_PMIC_LCDKBD_LED_DRIVER
+#include "pm.h"
+#endif /* FEATURE_PMIC_LCDKBD_LED_DRIVER */
+
+#ifdef DISP_DEVICE_18BPP
+#undef DISP_DEVICE_18BPP
+#define DISP_DEVICE_16BPP
+#endif
+
+#define QCIF_WIDTH        176
+#define QCIF_HEIGHT       220
+
+static void *DISP_CMD_PORT;
+static void *DISP_DATA_PORT;
+
+#define DISP_CMD_DISON    0xaf
+#define DISP_CMD_DISOFF   0xae
+#define DISP_CMD_DISNOR   0xa6
+#define DISP_CMD_DISINV   0xa7
+#define DISP_CMD_DISCTL   0xca
+#define DISP_CMD_GCP64    0xcb
+#define DISP_CMD_GCP16    0xcc
+#define DISP_CMD_GSSET    0xcd
+#define DISP_GS_2       0x02
+#define DISP_GS_16      0x01
+#define DISP_GS_64      0x00
+#define DISP_CMD_SLPIN    0x95
+#define DISP_CMD_SLPOUT   0x94
+#define DISP_CMD_SD_PSET  0x75
+#define DISP_CMD_MD_PSET  0x76
+#define DISP_CMD_SD_CSET  0x15
+#define DISP_CMD_MD_CSET  0x16
+#define DISP_CMD_DATCTL   0xbc
+#define DISP_DATCTL_666 0x08
+#define DISP_DATCTL_565 0x28
+#define DISP_DATCTL_444 0x38
+#define DISP_CMD_RAMWR    0x5c
+#define DISP_CMD_RAMRD    0x5d
+#define DISP_CMD_PTLIN    0xa8
+#define DISP_CMD_PTLOUT   0xa9
+#define DISP_CMD_ASCSET   0xaa
+#define DISP_CMD_SCSTART  0xab
+#define DISP_CMD_VOLCTL   0xc6
+#define DISP_VOLCTL_TONE 0x80
+#define DISP_CMD_NOp      0x25
+#define DISP_CMD_OSSEL    0xd0
+#define DISP_CMD_3500KSET 0xd1
+#define DISP_CMD_3500KEND 0xd2
+#define DISP_CMD_14MSET   0xd3
+#define DISP_CMD_14MEND   0xd4
+
+#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, cmd);
+
+#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, data);
+
+#define DISP_DATA_IN() inpw(DISP_DATA_PORT);
+
+/* Epson device column number starts at 2
+*/
+#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
+         DISP_CMD_OUT(DISP_CMD_SD_PSET) \
+         DISP_DATA_OUT((ulhc_row) & 0xFF) \
+         DISP_DATA_OUT((ulhc_row) >> 8) \
+         DISP_DATA_OUT((lrhc_row) & 0xFF) \
+         DISP_DATA_OUT((lrhc_row) >> 8) \
+         DISP_CMD_OUT(DISP_CMD_SD_CSET) \
+         DISP_DATA_OUT(((ulhc_col)+2) & 0xFF) \
+         DISP_DATA_OUT(((ulhc_col)+2) >> 8) \
+         DISP_DATA_OUT(((lrhc_col)+2) & 0xFF) \
+         DISP_DATA_OUT(((lrhc_col)+2) >> 8)
+
+#define DISP_MIN_CONTRAST      0
+#define DISP_MAX_CONTRAST      127
+#define DISP_DEFAULT_CONTRAST  80
+
+#define DISP_MIN_BACKLIGHT     0
+#define DISP_MAX_BACKLIGHT     15
+#define DISP_DEFAULT_BACKLIGHT 2
+
+#define WAIT_SEC(sec) mdelay((sec)/1000)
+
+static word disp_area_start_row;
+static word disp_area_end_row;
+static byte disp_contrast = DISP_DEFAULT_CONTRAST;
+static boolean disp_powered_up;
+static boolean disp_initialized = FALSE;
+/* For some reason the contrast set at init time is not good. Need to do
+ * it again
+ */
+static boolean display_on = FALSE;
+static void epsonQcif_disp_init(struct platform_device *pdev);
+static void epsonQcif_disp_set_contrast(word contrast);
+static void epsonQcif_disp_set_display_area(word start_row, word end_row);
+static int epsonQcif_disp_off(struct platform_device *pdev);
+static int epsonQcif_disp_on(struct platform_device *pdev);
+static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres);
+
+volatile word databack;
+static void epsonQcif_disp_init(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+
+       int i;
+
+       if (disp_initialized)
+               return;
+
+       mfd = platform_get_drvdata(pdev);
+
+       DISP_CMD_PORT = mfd->cmd_port;
+       DISP_DATA_PORT = mfd->data_port;
+
+       /* Sleep in */
+       DISP_CMD_OUT(DISP_CMD_SLPIN);
+
+       /* Display off */
+       DISP_CMD_OUT(DISP_CMD_DISOFF);
+
+       /* Display normal */
+       DISP_CMD_OUT(DISP_CMD_DISNOR);
+
+       /* Set data mode */
+       DISP_CMD_OUT(DISP_CMD_DATCTL);
+       DISP_DATA_OUT(DISP_DATCTL_565);
+
+       /* Set display timing */
+       DISP_CMD_OUT(DISP_CMD_DISCTL);
+       DISP_DATA_OUT(0x1c);    /* p1 */
+       DISP_DATA_OUT(0x02);    /* p1 */
+       DISP_DATA_OUT(0x82);    /* p2 */
+       DISP_DATA_OUT(0x00);    /* p3 */
+       DISP_DATA_OUT(0x00);    /* p4 */
+       DISP_DATA_OUT(0xe0);    /* p5 */
+       DISP_DATA_OUT(0x00);    /* p5 */
+       DISP_DATA_OUT(0xdc);    /* p6 */
+       DISP_DATA_OUT(0x00);    /* p6 */
+       DISP_DATA_OUT(0x02);    /* p7 */
+       DISP_DATA_OUT(0x00);    /* p8 */
+
+       /* Set 64 gray scale level */
+       DISP_CMD_OUT(DISP_CMD_GCP64);
+       DISP_DATA_OUT(0x08);    /* p01 */
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT(0x2a);    /* p02 */
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT(0x4e);    /* p03 */
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT(0x6b);    /* p04 */
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT(0x88);    /* p05 */
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT(0xa3);    /* p06 */
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT(0xba);    /* p07 */
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT(0xd1);    /* p08 */
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT(0xe5);    /* p09 */
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT(0xf3);    /* p10 */
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT(0x03);    /* p11 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x13);    /* p12 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x22);    /* p13 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x2f);    /* p14 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x3b);    /* p15 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x46);    /* p16 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x51);    /* p17 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x5b);    /* p18 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x64);    /* p19 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x6c);    /* p20 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x74);    /* p21 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x7c);    /* p22 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x83);    /* p23 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x8a);    /* p24 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x91);    /* p25 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x98);    /* p26 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x9f);    /* p27 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xa6);    /* p28 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xac);    /* p29 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xb2);    /* p30 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xb7);    /* p31 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xbc);    /* p32 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xc1);    /* p33 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xc6);    /* p34 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xcb);    /* p35 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xd0);    /* p36 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xd4);    /* p37 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xd8);    /* p38 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xdc);    /* p39 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xe0);    /* p40 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xe4);    /* p41 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xe8);    /* p42 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xec);    /* p43 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xf0);    /* p44 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xf4);    /* p45 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xf8);    /* p46 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xfb);    /* p47 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xfe);    /* p48 */
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0x01);    /* p49 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x03);    /* p50 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x05);    /* p51 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x07);    /* p52 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x09);    /* p53 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x0b);    /* p54 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x0d);    /* p55 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x0f);    /* p56 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x11);    /* p57 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x13);    /* p58 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x15);    /* p59 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x17);    /* p60 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x19);    /* p61 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x1b);    /* p62 */
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x1c);    /* p63 */
+       DISP_DATA_OUT(0x02);
+
+       /* Set 16 gray scale level */
+       DISP_CMD_OUT(DISP_CMD_GCP16);
+       DISP_DATA_OUT(0x1a);    /* p01 */
+       DISP_DATA_OUT(0x32);    /* p02 */
+       DISP_DATA_OUT(0x42);    /* p03 */
+       DISP_DATA_OUT(0x4c);    /* p04 */
+       DISP_DATA_OUT(0x58);    /* p05 */
+       DISP_DATA_OUT(0x5f);    /* p06 */
+       DISP_DATA_OUT(0x66);    /* p07 */
+       DISP_DATA_OUT(0x6b);    /* p08 */
+       DISP_DATA_OUT(0x70);    /* p09 */
+       DISP_DATA_OUT(0x74);    /* p10 */
+       DISP_DATA_OUT(0x78);    /* p11 */
+       DISP_DATA_OUT(0x7b);    /* p12 */
+       DISP_DATA_OUT(0x7e);    /* p13 */
+       DISP_DATA_OUT(0x80);    /* p14 */
+       DISP_DATA_OUT(0x82);    /* p15 */
+
+       /* Set DSP column */
+       DISP_CMD_OUT(DISP_CMD_MD_CSET);
+       DISP_DATA_OUT(0xff);
+       DISP_DATA_OUT(0x03);
+       DISP_DATA_OUT(0xff);
+       DISP_DATA_OUT(0x03);
+
+       /* Set DSP page */
+       DISP_CMD_OUT(DISP_CMD_MD_PSET);
+       DISP_DATA_OUT(0xff);
+       DISP_DATA_OUT(0x01);
+       DISP_DATA_OUT(0xff);
+       DISP_DATA_OUT(0x01);
+
+       /* Set ARM column */
+       DISP_CMD_OUT(DISP_CMD_SD_CSET);
+       DISP_DATA_OUT(0x02);
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT((QCIF_WIDTH + 1) & 0xFF);
+       DISP_DATA_OUT((QCIF_WIDTH + 1) >> 8);
+
+       /* Set ARM page */
+       DISP_CMD_OUT(DISP_CMD_SD_PSET);
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT(0x00);
+       DISP_DATA_OUT((QCIF_HEIGHT - 1) & 0xFF);
+       DISP_DATA_OUT((QCIF_HEIGHT - 1) >> 8);
+
+       /* Set 64 gray scales */
+       DISP_CMD_OUT(DISP_CMD_GSSET);
+       DISP_DATA_OUT(DISP_GS_64);
+
+       DISP_CMD_OUT(DISP_CMD_OSSEL);
+       DISP_DATA_OUT(0);
+
+       /* Sleep out */
+       DISP_CMD_OUT(DISP_CMD_SLPOUT);
+
+       WAIT_SEC(40000);
+
+       /* Initialize power IC */
+       DISP_CMD_OUT(DISP_CMD_VOLCTL);
+       DISP_DATA_OUT(DISP_VOLCTL_TONE);
+
+       WAIT_SEC(40000);
+
+       /* Set electronic volume, d'xx */
+       DISP_CMD_OUT(DISP_CMD_VOLCTL);
+       DISP_DATA_OUT(DISP_DEFAULT_CONTRAST);   /* value from 0 to 127 */
+
+       /* Initialize display data */
+       DISP_SET_RECT(0, (QCIF_HEIGHT - 1), 0, (QCIF_WIDTH - 1));
+       DISP_CMD_OUT(DISP_CMD_RAMWR);
+       for (i = 0; i < QCIF_HEIGHT * QCIF_WIDTH; i++)
+               DISP_DATA_OUT(0xffff);
+
+       DISP_CMD_OUT(DISP_CMD_RAMRD);
+       databack = DISP_DATA_IN();
+       databack = DISP_DATA_IN();
+       databack = DISP_DATA_IN();
+       databack = DISP_DATA_IN();
+
+       WAIT_SEC(80000);
+
+       DISP_CMD_OUT(DISP_CMD_DISON);
+
+       disp_area_start_row = 0;
+       disp_area_end_row = QCIF_HEIGHT - 1;
+       disp_powered_up = TRUE;
+       disp_initialized = TRUE;
+       epsonQcif_disp_set_display_area(0, QCIF_HEIGHT - 1);
+       display_on = TRUE;
+}
+
+static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres)
+{
+       if (!disp_initialized)
+               return;
+
+       DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
+       DISP_CMD_OUT(DISP_CMD_RAMWR);
+}
+
+static void epsonQcif_disp_set_display_area(word start_row, word end_row)
+{
+       if (!disp_initialized)
+               return;
+
+       if ((start_row == disp_area_start_row)
+           && (end_row == disp_area_end_row))
+               return;
+       disp_area_start_row = start_row;
+       disp_area_end_row = end_row;
+
+       /* Range checking
+        */
+       if (end_row >= QCIF_HEIGHT)
+               end_row = QCIF_HEIGHT - 1;
+       if (start_row > end_row)
+               start_row = end_row;
+
+       /* When display is not the full screen, gray scale is set to
+        ** 2; otherwise it is set to 64.
+        */
+       if ((start_row == 0) && (end_row == (QCIF_HEIGHT - 1))) {
+               /* The whole screen */
+               DISP_CMD_OUT(DISP_CMD_PTLOUT);
+               WAIT_SEC(10000);
+               DISP_CMD_OUT(DISP_CMD_DISOFF);
+               WAIT_SEC(100000);
+               DISP_CMD_OUT(DISP_CMD_GSSET);
+               DISP_DATA_OUT(DISP_GS_64);
+               WAIT_SEC(100000);
+               DISP_CMD_OUT(DISP_CMD_DISON);
+       } else {
+               /* partial screen */
+               DISP_CMD_OUT(DISP_CMD_PTLIN);
+               DISP_DATA_OUT(start_row);
+               DISP_DATA_OUT(start_row >> 8);
+               DISP_DATA_OUT(end_row);
+               DISP_DATA_OUT(end_row >> 8);
+               DISP_CMD_OUT(DISP_CMD_GSSET);
+               DISP_DATA_OUT(DISP_GS_2);
+       }
+}
+
+static int epsonQcif_disp_off(struct platform_device *pdev)
+{
+       if (!disp_initialized)
+               epsonQcif_disp_init(pdev);
+
+       if (display_on) {
+               DISP_CMD_OUT(DISP_CMD_DISOFF);
+               DISP_CMD_OUT(DISP_CMD_SLPIN);
+               display_on = FALSE;
+       }
+
+       return 0;
+}
+
+static int epsonQcif_disp_on(struct platform_device *pdev)
+{
+       if (!disp_initialized)
+               epsonQcif_disp_init(pdev);
+
+       if (!display_on) {
+               DISP_CMD_OUT(DISP_CMD_SLPOUT);
+               WAIT_SEC(40000);
+               DISP_CMD_OUT(DISP_CMD_DISON);
+               epsonQcif_disp_set_contrast(disp_contrast);
+               display_on = TRUE;
+       }
+
+       return 0;
+}
+
+static void epsonQcif_disp_set_contrast(word contrast)
+{
+       if (!disp_initialized)
+               return;
+
+       /* Initialize power IC, d'24 */
+       DISP_CMD_OUT(DISP_CMD_VOLCTL);
+       DISP_DATA_OUT(DISP_VOLCTL_TONE);
+
+       WAIT_SEC(40000);
+
+       /* Set electronic volume, d'xx */
+       DISP_CMD_OUT(DISP_CMD_VOLCTL);
+       if (contrast > 127)
+               contrast = 127;
+       DISP_DATA_OUT(contrast);        /* value from 0 to 127 */
+       disp_contrast = (byte) contrast;
+}                              /* End disp_set_contrast */
+
+static void epsonQcif_disp_clear_screen_area(
+       word start_row, word end_row, word start_column, word end_column) {
+       int32 i;
+
+       /* Clear the display screen */
+       DISP_SET_RECT(start_row, end_row, start_column, end_column);
+       DISP_CMD_OUT(DISP_CMD_RAMWR);
+       i = (end_row - start_row + 1) * (end_column - start_column + 1);
+       for (; i > 0; i--)
+               DISP_DATA_OUT(0xffff);
+}
+
+static int __init epsonQcif_probe(struct platform_device *pdev)
+{
+       msm_fb_add_device(pdev);
+
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = epsonQcif_probe,
+       .driver = {
+               .name   = "ebi2_epson_qcif",
+       },
+};
+
+static struct msm_fb_panel_data epsonQcif_panel_data = {
+       .on = epsonQcif_disp_on,
+       .off = epsonQcif_disp_off,
+       .set_rect = epsonQcif_disp_set_rect,
+};
+
+static struct platform_device this_device = {
+       .name   = "ebi2_epson_qcif",
+       .id     = 0,
+       .dev    = {
+               .platform_data = &epsonQcif_panel_data,
+       }
+};
+
+static int __init epsonQcif_init(void)
+{
+       int ret;
+       struct msm_panel_info *pinfo;
+
+       ret = platform_driver_register(&this_driver);
+       if (!ret) {
+               pinfo = &epsonQcif_panel_data.panel_info;
+               pinfo->xres = QCIF_WIDTH;
+               pinfo->yres = QCIF_HEIGHT;
+               pinfo->type = EBI2_PANEL;
+               pinfo->pdest = DISPLAY_2;
+               pinfo->wait_cycle = 0x808000;
+               pinfo->bpp = 16;
+               pinfo->fb_num = 2;
+               pinfo->lcd.vsync_enable = FALSE;
+
+               ret = platform_device_register(&this_device);
+               if (ret)
+                       platform_driver_unregister(&this_driver);
+       }
+
+       return ret;
+}
+
+module_init(epsonQcif_init);
diff --git a/drivers/staging/msm/ebi2_lcd.c b/drivers/staging/msm/ebi2_lcd.c
new file mode 100644 (file)
index 0000000..b41e123
--- /dev/null
@@ -0,0 +1,250 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+
+#include "msm_fb.h"
+
+static int ebi2_lcd_probe(struct platform_device *pdev);
+static int ebi2_lcd_remove(struct platform_device *pdev);
+
+static struct platform_driver ebi2_lcd_driver = {
+       .probe = ebi2_lcd_probe,
+       .remove = ebi2_lcd_remove,
+       .suspend = NULL,
+       .suspend_late = NULL,
+       .resume_early = NULL,
+       .resume = NULL,
+       .shutdown = NULL,
+       .driver = {
+                  .name = "ebi2_lcd",
+                  },
+};
+
+static void *ebi2_base;
+static void *ebi2_lcd_cfg0;
+static void *ebi2_lcd_cfg1;
+static void __iomem *lcd01_base;
+static void __iomem *lcd02_base;
+static int ebi2_lcd_resource_initialized;
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static int ebi2_lcd_probe(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+       struct platform_device *mdp_dev = NULL;
+       struct msm_fb_panel_data *pdata = NULL;
+       int rc, i;
+
+       if (pdev->id == 0) {
+               for (i = 0; i < pdev->num_resources; i++) {
+                       if (!strncmp(pdev->resource[i].name, "base", 4)) {
+                               ebi2_base = ioremap(pdev->resource[i].start,
+                                               pdev->resource[i].end -
+                                               pdev->resource[i].start + 1);
+                               if (!ebi2_base) {
+                                       printk(KERN_ERR
+                                               "ebi2_base ioremap failed!\n");
+                                       return -ENOMEM;
+                               }
+                               ebi2_lcd_cfg0 = (void *)(ebi2_base + 0x20);
+                               ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24);
+                       } else if (!strncmp(pdev->resource[i].name,
+                                               "lcd01", 5)) {
+                               lcd01_base = ioremap(pdev->resource[i].start,
+                                               pdev->resource[i].end -
+                                               pdev->resource[i].start + 1);
+                               if (!lcd01_base) {
+                                       printk(KERN_ERR
+                                               "lcd01_base ioremap failed!\n");
+                                       return -ENOMEM;
+                               }
+                       } else if (!strncmp(pdev->resource[i].name,
+                                               "lcd02", 5)) {
+                               lcd02_base = ioremap(pdev->resource[i].start,
+                                               pdev->resource[i].end -
+                                               pdev->resource[i].start + 1);
+                               if (!lcd02_base) {
+                                       printk(KERN_ERR
+                                               "lcd02_base ioremap failed!\n");
+                                       return -ENOMEM;
+                               }
+                       }
+               }
+               ebi2_lcd_resource_initialized = 1;
+               return 0;
+       }
+
+       if (!ebi2_lcd_resource_initialized)
+               return -EPERM;
+
+       mfd = platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+               return -ENOMEM;
+
+       if (ebi2_base == NULL)
+               return -ENOMEM;
+
+       mdp_dev = platform_device_alloc("mdp", pdev->id);
+       if (!mdp_dev)
+               return -ENOMEM;
+
+       /* link to the latest pdev */
+       mfd->pdev = mdp_dev;
+       mfd->dest = DISPLAY_LCD;
+
+       /* add panel data */
+       if (platform_device_add_data
+           (mdp_dev, pdev->dev.platform_data,
+            sizeof(struct msm_fb_panel_data))) {
+               printk(KERN_ERR "ebi2_lcd_probe: platform_device_add_data failed!\n");
+               platform_device_put(mdp_dev);
+               return -ENOMEM;
+       }
+
+       /* data chain */
+       pdata = mdp_dev->dev.platform_data;
+       pdata->on = panel_next_on;
+       pdata->off = panel_next_off;
+       pdata->next = pdev;
+
+       /* get/set panel specific fb info */
+       mfd->panel_info = pdata->panel_info;
+
+       if (mfd->panel_info.bpp == 24)
+               mfd->fb_imgType = MDP_RGB_888;
+       else
+               mfd->fb_imgType = MDP_RGB_565;
+
+       /* config msm ebi2 lcd register */
+       if (mfd->panel_info.pdest == DISPLAY_1) {
+               outp32(ebi2_base,
+                      (inp32(ebi2_base) & (~(EBI2_PRIM_LCD_CLR))) |
+                      EBI2_PRIM_LCD_SEL);
+               /*
+                * current design has one set of cfg0/1 register to control
+                * both EBI2 channels. so, we're using the PRIM channel to
+                * configure both.
+                */
+               outp32(ebi2_lcd_cfg0, mfd->panel_info.wait_cycle);
+               if (mfd->panel_info.bpp == 18)
+                       outp32(ebi2_lcd_cfg1, 0x01000000);
+               else
+                       outp32(ebi2_lcd_cfg1, 0x0);
+       } else {
+#ifdef DEBUG_EBI2_LCD
+               /*
+                * confliting with QCOM SURF FPGA CS.
+                * OEM should enable below for their CS mapping
+                */
+                outp32(ebi2_base, (inp32(ebi2_base)&(~(EBI2_SECD_LCD_CLR)))
+                                       |EBI2_SECD_LCD_SEL);
+#endif
+       }
+
+       /*
+        * map cs (chip select) address
+        */
+       if (mfd->panel_info.pdest == DISPLAY_1) {
+               mfd->cmd_port = lcd01_base;
+               mfd->data_port =
+                   (void *)((uint32) mfd->cmd_port + EBI2_PRIM_LCD_RS_PIN);
+               mfd->data_port_phys =
+                   (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN);
+       } else {
+               mfd->cmd_port = lcd01_base;
+               mfd->data_port =
+                   (void *)((uint32) mfd->cmd_port + EBI2_SECD_LCD_RS_PIN);
+               mfd->data_port_phys =
+                   (void *)(LCD_SECD_BASE_PHYS + EBI2_SECD_LCD_RS_PIN);
+       }
+
+       /*
+        * set driver data
+        */
+       platform_set_drvdata(mdp_dev, mfd);
+
+       /*
+        * register in mdp driver
+        */
+       rc = platform_device_add(mdp_dev);
+       if (rc) {
+               goto ebi2_lcd_probe_err;
+       }
+
+       pdev_list[pdev_list_cnt++] = pdev;
+       return 0;
+
+      ebi2_lcd_probe_err:
+       platform_device_put(mdp_dev);
+       return rc;
+}
+
+static int ebi2_lcd_remove(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+
+       mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return 0;
+
+       if (mfd->key != MFD_KEY)
+               return 0;
+
+       iounmap(mfd->cmd_port);
+
+       return 0;
+}
+
+static int ebi2_lcd_register_driver(void)
+{
+       return platform_driver_register(&ebi2_lcd_driver);
+}
+
+static int __init ebi2_lcd_driver_init(void)
+{
+       return ebi2_lcd_register_driver();
+}
+
+module_init(ebi2_lcd_driver_init);
\ No newline at end of file
diff --git a/drivers/staging/msm/ebi2_tmd20.c b/drivers/staging/msm/ebi2_tmd20.c
new file mode 100644 (file)
index 0000000..d66d039
--- /dev/null
@@ -0,0 +1,1122 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#include <linux/memory.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+/* #define TMD20QVGA_LCD_18BPP */
+#define QVGA_WIDTH        240
+#define QVGA_HEIGHT       320
+
+#ifdef TMD20QVGA_LCD_18BPP
+#define DISP_QVGA_18BPP(x)  ((((x)<<2) & 0x3FC00)|(( (x)<<1)& 0x1FE))
+#define DISP_REG(name)  uint32 register_##name;
+#define OUTPORT(x, y)  outpdw(x, y)
+#define INPORT(x)   inpdw(x)
+#else
+#define DISP_QVGA_18BPP(x)  (x)
+#define DISP_REG(name)  uint16 register_##name;
+#define OUTPORT(x, y)  outpw(x, y)
+#define INPORT(x)   intpw(x)
+#endif
+
+static void *DISP_CMD_PORT;
+static void *DISP_DATA_PORT;
+
+#define DISP_RNTI         0x10
+
+#define DISP_CMD_OUT(cmd) OUTPORT(DISP_CMD_PORT, DISP_QVGA_18BPP(cmd))
+#define DISP_DATA_OUT(data) OUTPORT(DISP_DATA_PORT, data)
+#define DISP_DATA_IN() INPORT(DISP_DATA_PORT)
+
+#if (defined(TMD20QVGA_LCD_18BPP))
+#define DISP_DATA_OUT_16TO18BPP(x) \
+       DISP_DATA_OUT((((x)&0xf800)<<2|((x)&0x80000)>>3) \
+                    | (((x)&0x7e0)<<1) \
+                    | (((x)&0x1F)<<1|((x)&0x10)>>4))
+#else
+#define DISP_DATA_OUT_16TO18BPP(x) \
+       DISP_DATA_OUT(x)
+#endif
+
+#define DISP_WRITE_OUT(addr, data) \
+   register_##addr = DISP_QVGA_18BPP(data); \
+   DISP_CMD_OUT(addr); \
+   DISP_DATA_OUT(register_##addr);
+
+#define DISP_UPDATE_VALUE(addr, bitmask, data) \
+   DISP_WRITE_OUT(##addr, (register_##addr & ~(bitmask)) | (data));
+
+#define DISP_VAL_IF(bitvalue, bitmask) \
+   ((bitvalue) ? (bitmask) : 0)
+
+/* QVGA = 256 x 320 */
+/* actual display is 240 x 320...offset by 0x10 */
+#define DISP_ROW_COL_TO_ADDR(row, col) ((row) * 0x100 + col)
+#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
+   { \
+   DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
+   DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, (lrhc_col) + tmd20qvga_panel_offset); \
+   DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, (ulhc_row)); \
+   DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, (lrhc_row)); \
+   DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
+   DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, (ulhc_row)); \
+   }
+
+#define WAIT_MSEC(msec) mdelay(msec)
+
+/*
+ * TMD QVGA Address
+ */
+/* Display Control */
+#define DISP_START_OSCILLATION_ADDR     0x000
+DISP_REG(DISP_START_OSCILLATION_ADDR)
+#define DISP_DRIVER_OUTPUT_CTL_ADDR     0x001
+    DISP_REG(DISP_DRIVER_OUTPUT_CTL_ADDR)
+#define DISP_LCD_DRIVING_SIG_ADDR     0x002
+    DISP_REG(DISP_LCD_DRIVING_SIG_ADDR)
+#define DISP_ENTRY_MODE_ADDR            0x003
+    DISP_REG(DISP_ENTRY_MODE_ADDR)
+#define DISP_DISPLAY_CTL_1_ADDR         0x007
+    DISP_REG(DISP_DISPLAY_CTL_1_ADDR)
+#define DISP_DISPLAY_CTL_2_ADDR         0x008
+    DISP_REG(DISP_DISPLAY_CTL_2_ADDR)
+
+/* DISPLAY MODE 0x009 partial display not supported */
+#define DISP_POWER_SUPPLY_INTF_ADDR     0x00A
+    DISP_REG(DISP_POWER_SUPPLY_INTF_ADDR)
+
+/* DISPLAY MODE 0x00B xZoom feature is not supported */
+#define DISP_EXT_DISPLAY_CTL_1_ADDR     0x00C
+    DISP_REG(DISP_EXT_DISPLAY_CTL_1_ADDR)
+
+#define DISP_FRAME_CYCLE_CTL_ADDR       0x00D
+    DISP_REG(DISP_FRAME_CYCLE_CTL_ADDR)
+
+#define DISP_EXT_DISPLAY_CTL_2_ADDR     0x00E
+    DISP_REG(DISP_EXT_DISPLAY_CTL_2_ADDR)
+
+#define DISP_EXT_DISPLAY_CTL_3_ADDR     0x00F
+    DISP_REG(DISP_EXT_DISPLAY_CTL_3_ADDR)
+
+#define DISP_LTPS_CTL_1_ADDR            0x012
+    DISP_REG(DISP_LTPS_CTL_1_ADDR)
+#define DISP_LTPS_CTL_2_ADDR            0x013
+    DISP_REG(DISP_LTPS_CTL_2_ADDR)
+#define DISP_LTPS_CTL_3_ADDR            0x014
+    DISP_REG(DISP_LTPS_CTL_3_ADDR)
+#define DISP_LTPS_CTL_4_ADDR            0x018
+    DISP_REG(DISP_LTPS_CTL_4_ADDR)
+#define DISP_LTPS_CTL_5_ADDR            0x019
+    DISP_REG(DISP_LTPS_CTL_5_ADDR)
+#define DISP_LTPS_CTL_6_ADDR            0x01A
+    DISP_REG(DISP_LTPS_CTL_6_ADDR)
+#define DISP_AMP_SETTING_ADDR           0x01C
+    DISP_REG(DISP_AMP_SETTING_ADDR)
+#define DISP_MODE_SETTING_ADDR          0x01D
+    DISP_REG(DISP_MODE_SETTING_ADDR)
+#define DISP_POFF_LN_SETTING_ADDR       0x01E
+    DISP_REG(DISP_POFF_LN_SETTING_ADDR)
+/* Power Contol */
+#define DISP_POWER_CTL_1_ADDR           0x100
+    DISP_REG(DISP_POWER_CTL_1_ADDR)
+#define DISP_POWER_CTL_2_ADDR           0x101
+    DISP_REG(DISP_POWER_CTL_2_ADDR)
+#define DISP_POWER_CTL_3_ADDR           0x102
+    DISP_REG(DISP_POWER_CTL_3_ADDR)
+#define DISP_POWER_CTL_4_ADDR           0x103
+    DISP_REG(DISP_POWER_CTL_4_ADDR)
+#define DISP_POWER_CTL_5_ADDR           0x104
+    DISP_REG(DISP_POWER_CTL_5_ADDR)
+#define DISP_POWER_CTL_6_ADDR           0x105
+    DISP_REG(DISP_POWER_CTL_6_ADDR)
+#define DISP_POWER_CTL_7_ADDR           0x106
+    DISP_REG(DISP_POWER_CTL_7_ADDR)
+/* RAM Access */
+#define DISP_RAM_ADDR_SET_1_ADDR        0x200
+    DISP_REG(DISP_RAM_ADDR_SET_1_ADDR)
+#define DISP_RAM_ADDR_SET_2_ADDR        0x201
+    DISP_REG(DISP_RAM_ADDR_SET_2_ADDR)
+#define DISP_CMD_RAMRD                  DISP_CMD_RAMWR
+#define DISP_CMD_RAMWR                  0x202
+    DISP_REG(DISP_CMD_RAMWR)
+#define DISP_RAM_DATA_MASK_1_ADDR       0x203
+    DISP_REG(DISP_RAM_DATA_MASK_1_ADDR)
+#define DISP_RAM_DATA_MASK_2_ADDR       0x204
+    DISP_REG(DISP_RAM_DATA_MASK_2_ADDR)
+/* Gamma Control, Contrast, Gray Scale Setting */
+#define DISP_GAMMA_CONTROL_1_ADDR       0x300
+    DISP_REG(DISP_GAMMA_CONTROL_1_ADDR)
+#define DISP_GAMMA_CONTROL_2_ADDR       0x301
+    DISP_REG(DISP_GAMMA_CONTROL_2_ADDR)
+#define DISP_GAMMA_CONTROL_3_ADDR       0x302
+    DISP_REG(DISP_GAMMA_CONTROL_3_ADDR)
+#define DISP_GAMMA_CONTROL_4_ADDR       0x303
+    DISP_REG(DISP_GAMMA_CONTROL_4_ADDR)
+#define DISP_GAMMA_CONTROL_5_ADDR       0x304
+    DISP_REG(DISP_GAMMA_CONTROL_5_ADDR)
+/* Coordinate Control */
+#define DISP_VERT_SCROLL_CTL_1_ADDR     0x400
+    DISP_REG(DISP_VERT_SCROLL_CTL_1_ADDR)
+#define DISP_VERT_SCROLL_CTL_2_ADDR     0x401
+    DISP_REG(DISP_VERT_SCROLL_CTL_2_ADDR)
+#define DISP_SCREEN_1_DRV_POS_1_ADDR    0x402
+    DISP_REG(DISP_SCREEN_1_DRV_POS_1_ADDR)
+#define DISP_SCREEN_1_DRV_POS_2_ADDR    0x403
+    DISP_REG(DISP_SCREEN_1_DRV_POS_2_ADDR)
+#define DISP_SCREEN_2_DRV_POS_1_ADDR    0x404
+    DISP_REG(DISP_SCREEN_2_DRV_POS_1_ADDR)
+#define DISP_SCREEN_2_DRV_POS_2_ADDR    0x405
+    DISP_REG(DISP_SCREEN_2_DRV_POS_2_ADDR)
+#define DISP_HORZ_RAM_ADDR_POS_1_ADDR   0x406
+    DISP_REG(DISP_HORZ_RAM_ADDR_POS_1_ADDR)
+#define DISP_HORZ_RAM_ADDR_POS_2_ADDR   0x407
+    DISP_REG(DISP_HORZ_RAM_ADDR_POS_2_ADDR)
+#define DISP_VERT_RAM_ADDR_POS_1_ADDR   0x408
+    DISP_REG(DISP_VERT_RAM_ADDR_POS_1_ADDR)
+#define DISP_VERT_RAM_ADDR_POS_2_ADDR   0x409
+    DISP_REG(DISP_VERT_RAM_ADDR_POS_2_ADDR)
+#define DISP_TMD_700_ADDR               0x700  /*  0x700 */
+    DISP_REG(DISP_TMD_700_ADDR)
+#define DISP_TMD_015_ADDR               0x015  /*  0x700 */
+    DISP_REG(DISP_TMD_015_ADDR)
+#define DISP_TMD_305_ADDR               0x305  /*  0x700 */
+    DISP_REG(DISP_TMD_305_ADDR)
+
+/*
+ * TMD QVGA Bit Definations
+ */
+
+#define DISP_BIT_IB15              0x8000
+#define DISP_BIT_IB14              0x4000
+#define DISP_BIT_IB13              0x2000
+#define DISP_BIT_IB12              0x1000
+#define DISP_BIT_IB11              0x0800
+#define DISP_BIT_IB10              0x0400
+#define DISP_BIT_IB09              0x0200
+#define DISP_BIT_IB08              0x0100
+#define DISP_BIT_IB07              0x0080
+#define DISP_BIT_IB06              0x0040
+#define DISP_BIT_IB05              0x0020
+#define DISP_BIT_IB04              0x0010
+#define DISP_BIT_IB03              0x0008
+#define DISP_BIT_IB02              0x0004
+#define DISP_BIT_IB01              0x0002
+#define DISP_BIT_IB00              0x0001
+/*
+ * Display Control
+ * DISP_START_OSCILLATION_ADDR     Start Oscillation
+ * DISP_DRIVER_OUTPUT_CTL_ADDR     Driver Output Control
+ */
+#define DISP_BITMASK_SS            DISP_BIT_IB08
+#define DISP_BITMASK_NL5           DISP_BIT_IB05
+#define DISP_BITMASK_NL4           DISP_BIT_IB04
+#define DISP_BITMASK_NL3           DISP_BIT_IB03
+#define DISP_BITMASK_NL2           DISP_BIT_IB02
+#define DISP_BITMASK_NL1           DISP_BIT_IB01
+#define DISP_BITMASK_NL0           DISP_BIT_IB00
+/* DISP_LCD_DRIVING_SIG_ADDR       LCD Driving Signal Setting */
+#define DISP_BITMASK_BC            DISP_BIT_IB09
+/* DISP_ENTRY_MODE_ADDR            Entry Mode */
+#define DISP_BITMASK_TRI           DISP_BIT_IB15
+#define DISP_BITMASK_DFM1          DISP_BIT_IB14
+#define DISP_BITMASK_DFM0          DISP_BIT_IB13
+#define DISP_BITMASK_BGR           DISP_BIT_IB12
+#define DISP_BITMASK_HWM0          DISP_BIT_IB08
+#define DISP_BITMASK_ID1           DISP_BIT_IB05
+#define DISP_BITMASK_ID0           DISP_BIT_IB04
+#define DISP_BITMASK_AM            DISP_BIT_IB03
+/* DISP_DISPLAY_CTL_1_ADDR         Display Control (1) */
+#define DISP_BITMASK_COL1          DISP_BIT_IB15
+#define DISP_BITMASK_COL0          DISP_BIT_IB14
+#define DISP_BITMASK_VLE2          DISP_BIT_IB10
+#define DISP_BITMASK_VLE1          DISP_BIT_IB09
+#define DISP_BITMASK_SPT           DISP_BIT_IB08
+#define DISP_BITMASK_PT1           DISP_BIT_IB07
+#define DISP_BITMASK_PT0           DISP_BIT_IB06
+#define DISP_BITMASK_REV           DISP_BIT_IB02
+/* DISP_DISPLAY_CTL_2_ADDR         Display Control (2) */
+#define DISP_BITMASK_FP3           DISP_BIT_IB11
+#define DISP_BITMASK_FP2           DISP_BIT_IB10
+#define DISP_BITMASK_FP1           DISP_BIT_IB09
+#define DISP_BITMASK_FP0           DISP_BIT_IB08
+#define DISP_BITMASK_BP3           DISP_BIT_IB03
+#define DISP_BITMASK_BP2           DISP_BIT_IB02
+#define DISP_BITMASK_BP1           DISP_BIT_IB01
+#define DISP_BITMASK_BP0           DISP_BIT_IB00
+/* DISP_POWER_SUPPLY_INTF_ADDR     Power Supply IC Interface Control */
+#define DISP_BITMASK_CSE           DISP_BIT_IB12
+#define DISP_BITMASK_TE            DISP_BIT_IB08
+#define DISP_BITMASK_IX3           DISP_BIT_IB03
+#define DISP_BITMASK_IX2           DISP_BIT_IB02
+#define DISP_BITMASK_IX1           DISP_BIT_IB01
+#define DISP_BITMASK_IX0           DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_1_ADDR     External Display Interface Control (1) */
+#define DISP_BITMASK_RM            DISP_BIT_IB08
+#define DISP_BITMASK_DM1           DISP_BIT_IB05
+#define DISP_BITMASK_DM0           DISP_BIT_IB04
+#define DISP_BITMASK_RIM1          DISP_BIT_IB01
+#define DISP_BITMASK_RIM0          DISP_BIT_IB00
+/* DISP_FRAME_CYCLE_CTL_ADDR       Frame Frequency Adjustment Control */
+#define DISP_BITMASK_DIVI1         DISP_BIT_IB09
+#define DISP_BITMASK_DIVI0         DISP_BIT_IB08
+#define DISP_BITMASK_RTNI4         DISP_BIT_IB04
+#define DISP_BITMASK_RTNI3         DISP_BIT_IB03
+#define DISP_BITMASK_RTNI2         DISP_BIT_IB02
+#define DISP_BITMASK_RTNI1         DISP_BIT_IB01
+#define DISP_BITMASK_RTNI0         DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_2_ADDR     External Display Interface Control (2) */
+#define DISP_BITMASK_DIVE1         DISP_BIT_IB09
+#define DISP_BITMASK_DIVE0         DISP_BIT_IB08
+#define DISP_BITMASK_RTNE7         DISP_BIT_IB07
+#define DISP_BITMASK_RTNE6         DISP_BIT_IB06
+#define DISP_BITMASK_RTNE5         DISP_BIT_IB05
+#define DISP_BITMASK_RTNE4         DISP_BIT_IB04
+#define DISP_BITMASK_RTNE3         DISP_BIT_IB03
+#define DISP_BITMASK_RTNE2         DISP_BIT_IB02
+#define DISP_BITMASK_RTNE1         DISP_BIT_IB01
+#define DISP_BITMASK_RTNE0         DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_3_ADDR     External Display Interface Control (3) */
+#define DISP_BITMASK_VSPL          DISP_BIT_IB04
+#define DISP_BITMASK_HSPL          DISP_BIT_IB03
+#define DISP_BITMASK_VPL           DISP_BIT_IB02
+#define DISP_BITMASK_EPL           DISP_BIT_IB01
+#define DISP_BITMASK_DPL           DISP_BIT_IB00
+/* DISP_LTPS_CTL_1_ADDR            LTPS Interface Control (1) */
+#define DISP_BITMASK_CLWI3         DISP_BIT_IB11
+#define DISP_BITMASK_CLWI2         DISP_BIT_IB10
+#define DISP_BITMASK_CLWI1         DISP_BIT_IB09
+#define DISP_BITMASK_CLWI0         DISP_BIT_IB08
+#define DISP_BITMASK_CLTI1         DISP_BIT_IB01
+#define DISP_BITMASK_CLTI0         DISP_BIT_IB00
+/* DISP_LTPS_CTL_2_ADDR            LTPS Interface Control (2) */
+#define DISP_BITMASK_OEVBI1        DISP_BIT_IB09
+#define DISP_BITMASK_OEVBI0        DISP_BIT_IB08
+#define DISP_BITMASK_OEVFI1        DISP_BIT_IB01
+#define DISP_BITMASK_OEVFI0        DISP_BIT_IB00
+/* DISP_LTPS_CTL_3_ADDR            LTPS Interface Control (3) */
+#define DISP_BITMASK_SHI1          DISP_BIT_IB01
+#define DISP_BITMASK_SHI0          DISP_BIT_IB00
+/* DISP_LTPS_CTL_4_ADDR            LTPS Interface Control (4) */
+#define DISP_BITMASK_CLWE5         DISP_BIT_IB13
+#define DISP_BITMASK_CLWE4         DISP_BIT_IB12
+#define DISP_BITMASK_CLWE3         DISP_BIT_IB11
+#define DISP_BITMASK_CLWE2         DISP_BIT_IB10
+#define DISP_BITMASK_CLWE1         DISP_BIT_IB09
+#define DISP_BITMASK_CLWE0         DISP_BIT_IB08
+#define DISP_BITMASK_CLTE3         DISP_BIT_IB03
+#define DISP_BITMASK_CLTE2         DISP_BIT_IB02
+#define DISP_BITMASK_CLTE1         DISP_BIT_IB01
+#define DISP_BITMASK_CLTE0         DISP_BIT_IB00
+/* DISP_LTPS_CTL_5_ADDR            LTPS Interface Control (5) */
+#define DISP_BITMASK_OEVBE3        DISP_BIT_IB11
+#define DISP_BITMASK_OEVBE2        DISP_BIT_IB10
+#define DISP_BITMASK_OEVBE1        DISP_BIT_IB09
+#define DISP_BITMASK_OEVBE0        DISP_BIT_IB08
+#define DISP_BITMASK_OEVFE3        DISP_BIT_IB03
+#define DISP_BITMASK_OEVFE2        DISP_BIT_IB02
+#define DISP_BITMASK_OEVFE1        DISP_BIT_IB01
+#define DISP_BITMASK_OEVFE0        DISP_BIT_IB00
+/* DISP_LTPS_CTL_6_ADDR            LTPS Interface Control (6) */
+#define DISP_BITMASK_SHE3          DISP_BIT_IB03
+#define DISP_BITMASK_SHE2          DISP_BIT_IB02
+#define DISP_BITMASK_SHE1          DISP_BIT_IB01
+#define DISP_BITMASK_SHE0          DISP_BIT_IB00
+/* DISP_AMP_SETTING_ADDR           Amplify Setting */
+#define DISP_BITMASK_ABSW1         DISP_BIT_IB01
+#define DISP_BITMASK_ABSW0         DISP_BIT_IB00
+/* DISP_MODE_SETTING_ADDR          Mode Setting */
+#define DISP_BITMASK_DSTB          DISP_BIT_IB02
+#define DISP_BITMASK_STB           DISP_BIT_IB00
+/* DISP_POFF_LN_SETTING_ADDR       Power Off Line Setting */
+#define DISP_BITMASK_POFH3         DISP_BIT_IB03
+#define DISP_BITMASK_POFH2         DISP_BIT_IB02
+#define DISP_BITMASK_POFH1         DISP_BIT_IB01
+#define DISP_BITMASK_POFH0         DISP_BIT_IB00
+
+/* Power Contol */
+/* DISP_POWER_CTL_1_ADDR           Power Control (1) */
+#define DISP_BITMASK_PO            DISP_BIT_IB11
+#define DISP_BITMASK_VCD           DISP_BIT_IB09
+#define DISP_BITMASK_VSC           DISP_BIT_IB08
+#define DISP_BITMASK_CON           DISP_BIT_IB07
+#define DISP_BITMASK_ASW1          DISP_BIT_IB06
+#define DISP_BITMASK_ASW0          DISP_BIT_IB05
+#define DISP_BITMASK_OEV           DISP_BIT_IB04
+#define DISP_BITMASK_OEVE          DISP_BIT_IB03
+#define DISP_BITMASK_FR            DISP_BIT_IB02
+#define DISP_BITMASK_D1            DISP_BIT_IB01
+#define DISP_BITMASK_D0            DISP_BIT_IB00
+/* DISP_POWER_CTL_2_ADDR           Power Control (2) */
+#define DISP_BITMASK_DC4           DISP_BIT_IB15
+#define DISP_BITMASK_DC3           DISP_BIT_IB14
+#define DISP_BITMASK_SAP2          DISP_BIT_IB13
+#define DISP_BITMASK_SAP1          DISP_BIT_IB12
+#define DISP_BITMASK_SAP0          DISP_BIT_IB11
+#define DISP_BITMASK_BT2           DISP_BIT_IB10
+#define DISP_BITMASK_BT1           DISP_BIT_IB09
+#define DISP_BITMASK_BT0           DISP_BIT_IB08
+#define DISP_BITMASK_DC2           DISP_BIT_IB07
+#define DISP_BITMASK_DC1           DISP_BIT_IB06
+#define DISP_BITMASK_DC0           DISP_BIT_IB05
+#define DISP_BITMASK_AP2           DISP_BIT_IB04
+#define DISP_BITMASK_AP1           DISP_BIT_IB03
+#define DISP_BITMASK_AP0           DISP_BIT_IB02
+/* DISP_POWER_CTL_3_ADDR           Power Control (3) */
+#define DISP_BITMASK_VGL4          DISP_BIT_IB10
+#define DISP_BITMASK_VGL3          DISP_BIT_IB09
+#define DISP_BITMASK_VGL2          DISP_BIT_IB08
+#define DISP_BITMASK_VGL1          DISP_BIT_IB07
+#define DISP_BITMASK_VGL0          DISP_BIT_IB06
+#define DISP_BITMASK_VGH4          DISP_BIT_IB04
+#define DISP_BITMASK_VGH3          DISP_BIT_IB03
+#define DISP_BITMASK_VGH2          DISP_BIT_IB02
+#define DISP_BITMASK_VGH1          DISP_BIT_IB01
+#define DISP_BITMASK_VGH0          DISP_BIT_IB00
+/* DISP_POWER_CTL_4_ADDR           Power Control (4) */
+#define DISP_BITMASK_VC2           DISP_BIT_IB02
+#define DISP_BITMASK_VC1           DISP_BIT_IB01
+#define DISP_BITMASK_VC0           DISP_BIT_IB00
+/* DISP_POWER_CTL_5_ADDR           Power Control (5) */
+#define DISP_BITMASK_VRL3          DISP_BIT_IB11
+#define DISP_BITMASK_VRL2          DISP_BIT_IB10
+#define DISP_BITMASK_VRL1          DISP_BIT_IB09
+#define DISP_BITMASK_VRL0          DISP_BIT_IB08
+#define DISP_BITMASK_PON           DISP_BIT_IB04
+#define DISP_BITMASK_VRH3          DISP_BIT_IB03
+#define DISP_BITMASK_VRH2          DISP_BIT_IB02
+#define DISP_BITMASK_VRH1          DISP_BIT_IB01
+#define DISP_BITMASK_VRH0          DISP_BIT_IB00
+/* DISP_POWER_CTL_6_ADDR           Power Control (6) */
+#define DISP_BITMASK_VCOMG         DISP_BIT_IB13
+#define DISP_BITMASK_VDV4          DISP_BIT_IB12
+#define DISP_BITMASK_VDV3          DISP_BIT_IB11
+#define DISP_BITMASK_VDV2          DISP_BIT_IB10
+#define DISP_BITMASK_VDV1          DISP_BIT_IB09
+#define DISP_BITMASK_VDV0          DISP_BIT_IB08
+#define DISP_BITMASK_VCM4          DISP_BIT_IB04
+#define DISP_BITMASK_VCM3          DISP_BIT_IB03
+#define DISP_BITMASK_VCM2          DISP_BIT_IB02
+#define DISP_BITMASK_VCM1          DISP_BIT_IB01
+#define DISP_BITMASK_VCM0          DISP_BIT_IB00
+/* RAM Access */
+/* DISP_RAM_ADDR_SET_1_ADDR        RAM Address Set (1) */
+#define DISP_BITMASK_AD7           DISP_BIT_IB07
+#define DISP_BITMASK_AD6           DISP_BIT_IB06
+#define DISP_BITMASK_AD5           DISP_BIT_IB05
+#define DISP_BITMASK_AD4           DISP_BIT_IB04
+#define DISP_BITMASK_AD3           DISP_BIT_IB03
+#define DISP_BITMASK_AD2           DISP_BIT_IB02
+#define DISP_BITMASK_AD1           DISP_BIT_IB01
+#define DISP_BITMASK_AD0           DISP_BIT_IB00
+/* DISP_RAM_ADDR_SET_2_ADDR        RAM Address Set (2) */
+#define DISP_BITMASK_AD16          DISP_BIT_IB08
+#define DISP_BITMASK_AD15          DISP_BIT_IB07
+#define DISP_BITMASK_AD14          DISP_BIT_IB06
+#define DISP_BITMASK_AD13          DISP_BIT_IB05
+#define DISP_BITMASK_AD12          DISP_BIT_IB04
+#define DISP_BITMASK_AD11          DISP_BIT_IB03
+#define DISP_BITMASK_AD10          DISP_BIT_IB02
+#define DISP_BITMASK_AD9           DISP_BIT_IB01
+#define DISP_BITMASK_AD8           DISP_BIT_IB00
+/*
+ * DISP_CMD_RAMWR       RAM Data Read/Write
+ * Use Data Bit Configuration
+ */
+/* DISP_RAM_DATA_MASK_1_ADDR       RAM Write Data Mask (1) */
+#define DISP_BITMASK_WM11          DISP_BIT_IB13
+#define DISP_BITMASK_WM10          DISP_BIT_IB12
+#define DISP_BITMASK_WM9           DISP_BIT_IB11
+#define DISP_BITMASK_WM8           DISP_BIT_IB10
+#define DISP_BITMASK_WM7           DISP_BIT_IB09
+#define DISP_BITMASK_WM6           DISP_BIT_IB08
+#define DISP_BITMASK_WM5           DISP_BIT_IB05
+#define DISP_BITMASK_WM4           DISP_BIT_IB04
+#define DISP_BITMASK_WM3           DISP_BIT_IB03
+#define DISP_BITMASK_WM2           DISP_BIT_IB02
+#define DISP_BITMASK_WM1           DISP_BIT_IB01
+#define DISP_BITMASK_WM0           DISP_BIT_IB00
+/* DISP_RAM_DATA_MASK_2_ADDR       RAM Write Data Mask (2) */
+#define DISP_BITMASK_WM17          DISP_BIT_IB05
+#define DISP_BITMASK_WM16          DISP_BIT_IB04
+#define DISP_BITMASK_WM15          DISP_BIT_IB03
+#define DISP_BITMASK_WM14          DISP_BIT_IB02
+#define DISP_BITMASK_WM13          DISP_BIT_IB01
+#define DISP_BITMASK_WM12          DISP_BIT_IB00
+/*Gamma Control */
+/* DISP_GAMMA_CONTROL_1_ADDR       Gamma Control (1) */
+#define DISP_BITMASK_PKP12         DISP_BIT_IB10
+#define DISP_BITMASK_PKP11         DISP_BIT_IB08
+#define DISP_BITMASK_PKP10         DISP_BIT_IB09
+#define DISP_BITMASK_PKP02         DISP_BIT_IB02
+#define DISP_BITMASK_PKP01         DISP_BIT_IB01
+#define DISP_BITMASK_PKP00         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_2_ADDR       Gamma Control (2) */
+#define DISP_BITMASK_PKP32         DISP_BIT_IB10
+#define DISP_BITMASK_PKP31         DISP_BIT_IB09
+#define DISP_BITMASK_PKP30         DISP_BIT_IB08
+#define DISP_BITMASK_PKP22         DISP_BIT_IB02
+#define DISP_BITMASK_PKP21         DISP_BIT_IB01
+#define DISP_BITMASK_PKP20         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_3_ADDR       Gamma Control (3) */
+#define DISP_BITMASK_PKP52         DISP_BIT_IB10
+#define DISP_BITMASK_PKP51         DISP_BIT_IB09
+#define DISP_BITMASK_PKP50         DISP_BIT_IB08
+#define DISP_BITMASK_PKP42         DISP_BIT_IB02
+#define DISP_BITMASK_PKP41         DISP_BIT_IB01
+#define DISP_BITMASK_PKP40         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_4_ADDR       Gamma Control (4) */
+#define DISP_BITMASK_PRP12         DISP_BIT_IB10
+#define DISP_BITMASK_PRP11         DISP_BIT_IB08
+#define DISP_BITMASK_PRP10         DISP_BIT_IB09
+#define DISP_BITMASK_PRP02         DISP_BIT_IB02
+#define DISP_BITMASK_PRP01         DISP_BIT_IB01
+#define DISP_BITMASK_PRP00         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_5_ADDR       Gamma Control (5) */
+#define DISP_BITMASK_VRP14         DISP_BIT_IB12
+#define DISP_BITMASK_VRP13         DISP_BIT_IB11
+#define DISP_BITMASK_VRP12         DISP_BIT_IB10
+#define DISP_BITMASK_VRP11         DISP_BIT_IB08
+#define DISP_BITMASK_VRP10         DISP_BIT_IB09
+#define DISP_BITMASK_VRP03         DISP_BIT_IB03
+#define DISP_BITMASK_VRP02         DISP_BIT_IB02
+#define DISP_BITMASK_VRP01         DISP_BIT_IB01
+#define DISP_BITMASK_VRP00         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_6_ADDR       Gamma Control (6) */
+#define DISP_BITMASK_PKN12         DISP_BIT_IB10
+#define DISP_BITMASK_PKN11         DISP_BIT_IB08
+#define DISP_BITMASK_PKN10         DISP_BIT_IB09
+#define DISP_BITMASK_PKN02         DISP_BIT_IB02
+#define DISP_BITMASK_PKN01         DISP_BIT_IB01
+#define DISP_BITMASK_PKN00         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_7_ADDR       Gamma Control (7) */
+#define DISP_BITMASK_PKN32         DISP_BIT_IB10
+#define DISP_BITMASK_PKN31         DISP_BIT_IB08
+#define DISP_BITMASK_PKN30         DISP_BIT_IB09
+#define DISP_BITMASK_PKN22         DISP_BIT_IB02
+#define DISP_BITMASK_PKN21         DISP_BIT_IB01
+#define DISP_BITMASK_PKN20         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_8_ADDR       Gamma Control (8) */
+#define DISP_BITMASK_PKN52         DISP_BIT_IB10
+#define DISP_BITMASK_PKN51         DISP_BIT_IB08
+#define DISP_BITMASK_PKN50         DISP_BIT_IB09
+#define DISP_BITMASK_PKN42         DISP_BIT_IB02
+#define DISP_BITMASK_PKN41         DISP_BIT_IB01
+#define DISP_BITMASK_PKN40         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_9_ADDR       Gamma Control (9) */
+#define DISP_BITMASK_PRN12         DISP_BIT_IB10
+#define DISP_BITMASK_PRN11         DISP_BIT_IB08
+#define DISP_BITMASK_PRN10         DISP_BIT_IB09
+#define DISP_BITMASK_PRN02         DISP_BIT_IB02
+#define DISP_BITMASK_PRN01         DISP_BIT_IB01
+#define DISP_BITMASK_PRN00         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_10_ADDR      Gamma Control (10) */
+#define DISP_BITMASK_VRN14         DISP_BIT_IB12
+#define DISP_BITMASK_VRN13         DISP_BIT_IB11
+#define DISP_BITMASK_VRN12         DISP_BIT_IB10
+#define DISP_BITMASK_VRN11         DISP_BIT_IB08
+#define DISP_BITMASK_VRN10         DISP_BIT_IB09
+#define DISP_BITMASK_VRN03         DISP_BIT_IB03
+#define DISP_BITMASK_VRN02         DISP_BIT_IB02
+#define DISP_BITMASK_VRN01         DISP_BIT_IB01
+#define DISP_BITMASK_VRN00         DISP_BIT_IB00
+/* Coordinate Control */
+/* DISP_VERT_SCROLL_CTL_1_ADDR     Vertical Scroll Control (1) */
+#define DISP_BITMASK_VL18          DISP_BIT_IB08
+#define DISP_BITMASK_VL17          DISP_BIT_IB07
+#define DISP_BITMASK_VL16          DISP_BIT_IB06
+#define DISP_BITMASK_VL15          DISP_BIT_IB05
+#define DISP_BITMASK_VL14          DISP_BIT_IB04
+#define DISP_BITMASK_VL13          DISP_BIT_IB03
+#define DISP_BITMASK_VL12          DISP_BIT_IB02
+#define DISP_BITMASK_VL11          DISP_BIT_IB01
+#define DISP_BITMASK_VL10          DISP_BIT_IB00
+/* DISP_VERT_SCROLL_CTL_2_ADDR     Vertical Scroll Control (2) */
+#define DISP_BITMASK_VL28          DISP_BIT_IB08
+#define DISP_BITMASK_VL27          DISP_BIT_IB07
+#define DISP_BITMASK_VL26          DISP_BIT_IB06
+#define DISP_BITMASK_VL25          DISP_BIT_IB05
+#define DISP_BITMASK_VL24          DISP_BIT_IB04
+#define DISP_BITMASK_VL23          DISP_BIT_IB03
+#define DISP_BITMASK_VL22          DISP_BIT_IB02
+#define DISP_BITMASK_VL21          DISP_BIT_IB01
+#define DISP_BITMASK_VL20          DISP_BIT_IB00
+/* DISP_SCREEN_1_DRV_POS_1_ADDR    First Screen Driving Position (1) */
+#define DISP_BITMASK_SS18          DISP_BIT_IB08
+#define DISP_BITMASK_SS17          DISP_BIT_IB07
+#define DISP_BITMASK_SS16          DISP_BIT_IB06
+#define DISP_BITMASK_SS15          DISP_BIT_IB05
+#define DISP_BITMASK_SS14          DISP_BIT_IB04
+#define DISP_BITMASK_SS13          DISP_BIT_IB03
+#define DISP_BITMASK_SS12          DISP_BIT_IB02
+#define DISP_BITMASK_SS11          DISP_BIT_IB01
+#define DISP_BITMASK_SS10          DISP_BIT_IB00
+/* DISP_SCREEN_1_DRV_POS_2_ADDR    First Screen Driving Position (2) */
+#define DISP_BITMASK_SE18          DISP_BIT_IB08
+#define DISP_BITMASK_SE17          DISP_BIT_IB07
+#define DISP_BITMASK_SE16          DISP_BIT_IB06
+#define DISP_BITMASK_SE15          DISP_BIT_IB05
+#define DISP_BITMASK_SE14          DISP_BIT_IB04
+#define DISP_BITMASK_SE13          DISP_BIT_IB03
+#define DISP_BITMASK_SE12          DISP_BIT_IB02
+#define DISP_BITMASK_SE11          DISP_BIT_IB01
+#define DISP_BITMASK_SE10          DISP_BIT_IB00
+/* DISP_SCREEN_2_DRV_POS_1_ADDR    Second Screen Driving Position (1) */
+#define DISP_BITMASK_SS28          DISP_BIT_IB08
+#define DISP_BITMASK_SS27          DISP_BIT_IB07
+#define DISP_BITMASK_SS26          DISP_BIT_IB06
+#define DISP_BITMASK_SS25          DISP_BIT_IB05
+#define DISP_BITMASK_SS24          DISP_BIT_IB04
+#define DISP_BITMASK_SS23          DISP_BIT_IB03
+#define DISP_BITMASK_SS22          DISP_BIT_IB02
+#define DISP_BITMASK_SS21          DISP_BIT_IB01
+#define DISP_BITMASK_SS20          DISP_BIT_IB00
+/* DISP_SCREEN_3_DRV_POS_2_ADDR    Second Screen Driving Position (2) */
+#define DISP_BITMASK_SE28          DISP_BIT_IB08
+#define DISP_BITMASK_SE27          DISP_BIT_IB07
+#define DISP_BITMASK_SE26          DISP_BIT_IB06
+#define DISP_BITMASK_SE25          DISP_BIT_IB05
+#define DISP_BITMASK_SE24          DISP_BIT_IB04
+#define DISP_BITMASK_SE23          DISP_BIT_IB03
+#define DISP_BITMASK_SE22          DISP_BIT_IB02
+#define DISP_BITMASK_SE21          DISP_BIT_IB01
+#define DISP_BITMASK_SE20          DISP_BIT_IB00
+/* DISP_HORZ_RAM_ADDR_POS_1_ADDR   Horizontal RAM Address Position (1) */
+#define DISP_BITMASK_HSA7          DISP_BIT_IB07
+#define DISP_BITMASK_HSA6          DISP_BIT_IB06
+#define DISP_BITMASK_HSA5          DISP_BIT_IB05
+#define DISP_BITMASK_HSA4          DISP_BIT_IB04
+#define DISP_BITMASK_HSA3          DISP_BIT_IB03
+#define DISP_BITMASK_HSA2          DISP_BIT_IB02
+#define DISP_BITMASK_HSA1          DISP_BIT_IB01
+#define DISP_BITMASK_HSA0          DISP_BIT_IB00
+/* DISP_HORZ_RAM_ADDR_POS_2_ADDR   Horizontal RAM Address Position (2) */
+#define DISP_BITMASK_HEA7          DISP_BIT_IB07
+#define DISP_BITMASK_HEA6          DISP_BIT_IB06
+#define DISP_BITMASK_HEA5          DISP_BIT_IB05
+#define DISP_BITMASK_HEA4          DISP_BIT_IB04
+#define DISP_BITMASK_HEA3          DISP_BIT_IB03
+#define DISP_BITMASK_HEA2          DISP_BIT_IB02
+#define DISP_BITMASK_HEA1          DISP_BIT_IB01
+#define DISP_BITMASK_HEA0          DISP_BIT_IB00
+/* DISP_VERT_RAM_ADDR_POS_1_ADDR   Vertical RAM Address Position (1) */
+#define DISP_BITMASK_VSA8          DISP_BIT_IB08
+#define DISP_BITMASK_VSA7          DISP_BIT_IB07
+#define DISP_BITMASK_VSA6          DISP_BIT_IB06
+#define DISP_BITMASK_VSA5          DISP_BIT_IB05
+#define DISP_BITMASK_VSA4          DISP_BIT_IB04
+#define DISP_BITMASK_VSA3          DISP_BIT_IB03
+#define DISP_BITMASK_VSA2          DISP_BIT_IB02
+#define DISP_BITMASK_VSA1          DISP_BIT_IB01
+#define DISP_BITMASK_VSA0          DISP_BIT_IB00
+/* DISP_VERT_RAM_ADDR_POS_2_ADDR   Vertical RAM Address Position (2) */
+#define DISP_BITMASK_VEA8          DISP_BIT_IB08
+#define DISP_BITMASK_VEA7          DISP_BIT_IB07
+#define DISP_BITMASK_VEA6          DISP_BIT_IB06
+#define DISP_BITMASK_VEA5          DISP_BIT_IB05
+#define DISP_BITMASK_VEA4          DISP_BIT_IB04
+#define DISP_BITMASK_VEA3          DISP_BIT_IB03
+#define DISP_BITMASK_VEA2          DISP_BIT_IB02
+#define DISP_BITMASK_VEA1          DISP_BIT_IB01
+#define DISP_BITMASK_VEA0          DISP_BIT_IB00
+static word disp_area_start_row;
+static word disp_area_end_row;
+static boolean disp_initialized = FALSE;
+/* For some reason the contrast set at init time is not good. Need to do
+* it again
+*/
+static boolean display_on = FALSE;
+
+static uint32 tmd20qvga_lcd_rev;
+uint16 tmd20qvga_panel_offset;
+
+#ifdef DISP_DEVICE_8BPP
+static word convert_8_to_16_tbl[256] = {
+       0x0000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000, 0xE000,
+       0x0100, 0x2100, 0x4100, 0x6100, 0x8100, 0xA100, 0xC100, 0xE100,
+       0x0200, 0x2200, 0x4200, 0x6200, 0x8200, 0xA200, 0xC200, 0xE200,
+       0x0300, 0x2300, 0x4300, 0x6300, 0x8300, 0xA300, 0xC300, 0xE300,
+       0x0400, 0x2400, 0x4400, 0x6400, 0x8400, 0xA400, 0xC400, 0xE400,
+       0x0500, 0x2500, 0x4500, 0x6500, 0x8500, 0xA500, 0xC500, 0xE500,
+       0x0600, 0x2600, 0x4600, 0x6600, 0x8600, 0xA600, 0xC600, 0xE600,
+       0x0700, 0x2700, 0x4700, 0x6700, 0x8700, 0xA700, 0xC700, 0xE700,
+       0x0008, 0x2008, 0x4008, 0x6008, 0x8008, 0xA008, 0xC008, 0xE008,
+       0x0108, 0x2108, 0x4108, 0x6108, 0x8108, 0xA108, 0xC108, 0xE108,
+       0x0208, 0x2208, 0x4208, 0x6208, 0x8208, 0xA208, 0xC208, 0xE208,
+       0x0308, 0x2308, 0x4308, 0x6308, 0x8308, 0xA308, 0xC308, 0xE308,
+       0x0408, 0x2408, 0x4408, 0x6408, 0x8408, 0xA408, 0xC408, 0xE408,
+       0x0508, 0x2508, 0x4508, 0x6508, 0x8508, 0xA508, 0xC508, 0xE508,
+       0x0608, 0x2608, 0x4608, 0x6608, 0x8608, 0xA608, 0xC608, 0xE608,
+       0x0708, 0x2708, 0x4708, 0x6708, 0x8708, 0xA708, 0xC708, 0xE708,
+       0x0010, 0x2010, 0x4010, 0x6010, 0x8010, 0xA010, 0xC010, 0xE010,
+       0x0110, 0x2110, 0x4110, 0x6110, 0x8110, 0xA110, 0xC110, 0xE110,
+       0x0210, 0x2210, 0x4210, 0x6210, 0x8210, 0xA210, 0xC210, 0xE210,
+       0x0310, 0x2310, 0x4310, 0x6310, 0x8310, 0xA310, 0xC310, 0xE310,
+       0x0410, 0x2410, 0x4410, 0x6410, 0x8410, 0xA410, 0xC410, 0xE410,
+       0x0510, 0x2510, 0x4510, 0x6510, 0x8510, 0xA510, 0xC510, 0xE510,
+       0x0610, 0x2610, 0x4610, 0x6610, 0x8610, 0xA610, 0xC610, 0xE610,
+       0x0710, 0x2710, 0x4710, 0x6710, 0x8710, 0xA710, 0xC710, 0xE710,
+       0x0018, 0x2018, 0x4018, 0x6018, 0x8018, 0xA018, 0xC018, 0xE018,
+       0x0118, 0x2118, 0x4118, 0x6118, 0x8118, 0xA118, 0xC118, 0xE118,
+       0x0218, 0x2218, 0x4218, 0x6218, 0x8218, 0xA218, 0xC218, 0xE218,
+       0x0318, 0x2318, 0x4318, 0x6318, 0x8318, 0xA318, 0xC318, 0xE318,
+       0x0418, 0x2418, 0x4418, 0x6418, 0x8418, 0xA418, 0xC418, 0xE418,
+       0x0518, 0x2518, 0x4518, 0x6518, 0x8518, 0xA518, 0xC518, 0xE518,
+       0x0618, 0x2618, 0x4618, 0x6618, 0x8618, 0xA618, 0xC618, 0xE618,
+       0x0718, 0x2718, 0x4718, 0x6718, 0x8718, 0xA718, 0xC718, 0xE718
+};
+#endif /* DISP_DEVICE_8BPP */
+
+static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres);
+static void tmd20qvga_disp_init(struct platform_device *pdev);
+static void tmd20qvga_disp_set_contrast(void);
+static void tmd20qvga_disp_set_display_area(word start_row, word end_row);
+static int tmd20qvga_disp_off(struct platform_device *pdev);
+static int tmd20qvga_disp_on(struct platform_device *pdev);
+static void tmd20qvga_set_revId(int);
+
+/* future use */
+void tmd20qvga_disp_clear_screen_area(word start_row, word end_row,
+                                     word start_column, word end_column);
+
+static void tmd20qvga_set_revId(int id)
+{
+
+       tmd20qvga_lcd_rev = id;
+
+       if (tmd20qvga_lcd_rev == 1)
+               tmd20qvga_panel_offset = 0x10;
+       else
+               tmd20qvga_panel_offset = 0;
+}
+
+static void tmd20qvga_disp_init(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+
+       if (disp_initialized)
+               return;
+
+       mfd = platform_get_drvdata(pdev);
+
+       DISP_CMD_PORT = mfd->cmd_port;
+       DISP_DATA_PORT = mfd->data_port;
+
+#ifdef TMD20QVGA_LCD_18BPP
+       tmd20qvga_set_revId(2);
+#else
+       tmd20qvga_set_revId(1);
+#endif
+
+       disp_initialized = TRUE;
+       tmd20qvga_disp_set_contrast();
+       tmd20qvga_disp_set_display_area(0, QVGA_HEIGHT - 1);
+}
+
+static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres)
+{
+       if (!disp_initialized)
+               return;
+
+       DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
+
+       DISP_CMD_OUT(DISP_CMD_RAMWR);
+}
+
+static void tmd20qvga_disp_set_display_area(word start_row, word end_row)
+{
+       word start_driving = start_row;
+       word end_driving = end_row;
+
+       if (!disp_initialized)
+               return;
+
+       /* Range checking
+        */
+       if (end_driving >= QVGA_HEIGHT)
+               end_driving = QVGA_HEIGHT - 1;
+       if (start_driving > end_driving) {
+               /* Probably Backwards Switch */
+               start_driving = end_driving;
+               end_driving = start_row;        /* Has not changed */
+               if (end_driving >= QVGA_HEIGHT)
+                       end_driving = QVGA_HEIGHT - 1;
+       }
+
+       if ((start_driving == disp_area_start_row)
+           && (end_driving == disp_area_end_row))
+               return;
+
+       disp_area_start_row = start_driving;
+       disp_area_end_row = end_driving;
+
+       DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR,
+                      DISP_VAL_IF(start_driving & 0x100,
+                                  DISP_BITMASK_SS18) |
+                      DISP_VAL_IF(start_driving & 0x080,
+                                  DISP_BITMASK_SS17) |
+                      DISP_VAL_IF(start_driving & 0x040,
+                                  DISP_BITMASK_SS16) |
+                      DISP_VAL_IF(start_driving & 0x020,
+                                  DISP_BITMASK_SS15) |
+                      DISP_VAL_IF(start_driving & 0x010,
+                                  DISP_BITMASK_SS14) |
+                      DISP_VAL_IF(start_driving & 0x008,
+                                  DISP_BITMASK_SS13) |
+                      DISP_VAL_IF(start_driving & 0x004,
+                                  DISP_BITMASK_SS12) |
+                      DISP_VAL_IF(start_driving & 0x002,
+                                  DISP_BITMASK_SS11) |
+                      DISP_VAL_IF(start_driving & 0x001, DISP_BITMASK_SS10));
+
+       DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR,
+                       DISP_VAL_IF(end_driving & 0x100, DISP_BITMASK_SE18) |
+                       DISP_VAL_IF(end_driving & 0x080, DISP_BITMASK_SE17) |
+                       DISP_VAL_IF(end_driving & 0x040, DISP_BITMASK_SE16) |
+                       DISP_VAL_IF(end_driving & 0x020, DISP_BITMASK_SE15) |
+                       DISP_VAL_IF(end_driving & 0x010, DISP_BITMASK_SE14) |
+                       DISP_VAL_IF(end_driving & 0x008, DISP_BITMASK_SE13) |
+                       DISP_VAL_IF(end_driving & 0x004, DISP_BITMASK_SE12) |
+                       DISP_VAL_IF(end_driving & 0x002, DISP_BITMASK_SE11) |
+                       DISP_VAL_IF(end_driving & 0x001, DISP_BITMASK_SE10));
+}
+
+static int tmd20qvga_disp_off(struct platform_device *pdev)
+{
+       if (!disp_initialized)
+               tmd20qvga_disp_init(pdev);
+
+       if (display_on) {
+               if (tmd20qvga_lcd_rev == 2) {
+                       DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000A);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFEE);
+                       WAIT_MSEC(40);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xF812);
+                       WAIT_MSEC(40);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xE811);
+                       WAIT_MSEC(40);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC011);
+                       WAIT_MSEC(40);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x4011);
+                       WAIT_MSEC(20);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0010);
+
+               } else {
+                       DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000F);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFE);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+                       WAIT_MSEC(40);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BED);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+                       WAIT_MSEC(40);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x00CD);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+                       WAIT_MSEC(20);
+                       DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0);
+               }
+
+               DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0004);
+               DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0000);
+
+               display_on = FALSE;
+       }
+
+       return 0;
+}
+
+static int tmd20qvga_disp_on(struct platform_device *pdev)
+{
+       if (!disp_initialized)
+               tmd20qvga_disp_init(pdev);
+
+       if (!display_on) {
+               /* Deep Stand-by -> Stand-by */
+               DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+               WAIT_MSEC(1);
+               DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+               WAIT_MSEC(1);
+               DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+               WAIT_MSEC(1);
+
+               /* OFF -> Deep Stan-By -> Stand-by */
+               /* let's change the state from "Stand-by" to "Sleep" */
+               DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0005);
+               WAIT_MSEC(1);
+
+               /* Sleep -> Displaying */
+               DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0001);
+               DISP_WRITE_OUT(DISP_DRIVER_OUTPUT_CTL_ADDR, 0x0127);
+               DISP_WRITE_OUT(DISP_LCD_DRIVING_SIG_ADDR, 0x200);
+               /* fast write mode */
+               DISP_WRITE_OUT(DISP_ENTRY_MODE_ADDR, 0x0130);
+               if (tmd20qvga_lcd_rev == 2)
+                       DISP_WRITE_OUT(DISP_TMD_700_ADDR, 0x0003);
+               /* back porch = 14 + front porch = 2 --> 16 lines */
+               if (tmd20qvga_lcd_rev == 2) {
+#ifdef TMD20QVGA_LCD_18BPP
+                       /* 256k color */
+                       DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0000);
+#else
+                       /* 65k color */
+                       DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4000);
+#endif
+                       DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x0302);
+               } else {
+#ifdef TMD20QVGA_LCD_18BPP
+                       /* 256k color */
+                       DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0004);
+#else
+                       /* 65k color */
+                       DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4004);
+#endif
+                       DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x020E);
+               }
+               /* 16 bit one transfer */
+               if (tmd20qvga_lcd_rev == 2) {
+                       DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0000);
+                       DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
+                       DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0302);
+                       DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0102);
+                       DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
+                       DISP_WRITE_OUT(DISP_TMD_015_ADDR, 0x2000);
+
+                       DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
+                       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+                       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0304);
+                       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
+                       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+                       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0101);
+                       DISP_WRITE_OUT(DISP_TMD_305_ADDR, 0);
+
+                       DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
+                       DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x077D);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0005);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0000);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0015);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC010);
+                       WAIT_MSEC(1);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x0001);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFFE);
+                       WAIT_MSEC(60);
+               } else {
+                       DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0001);
+                       DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
+                       DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0301);
+                       DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0001);
+                       DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
+                       DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
+                       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0507);
+                       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0405);
+                       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0607);
+                       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0502);
+                       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0301);
+                       DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
+                       DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
+                       DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x0795);
+
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0102);
+                       WAIT_MSEC(1);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0450);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0103);
+                       WAIT_MSEC(1);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0008);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0104);
+                       WAIT_MSEC(1);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0C00);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0105);
+                       WAIT_MSEC(1);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_7_ADDR, 0x0000);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0106);
+                       WAIT_MSEC(1);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0801);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+                       WAIT_MSEC(1);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x001F);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
+                       WAIT_MSEC(60);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x009F);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
+                       WAIT_MSEC(10);
+
+                       DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, 0x0010);
+                       DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, 0x00FF);
+                       DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, 0x0000);
+                       DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, 0x013F);
+                       /* RAM starts at address 0x10 */
+                       DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, 0x0010);
+                       DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, 0x0000);
+
+                       /* lcd controller uses internal clock, not ext. vsync */
+                       DISP_CMD_OUT(DISP_CMD_RAMWR);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0881);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+                       WAIT_MSEC(40);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BE1);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+                       WAIT_MSEC(40);
+
+                       DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFF);
+                       DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+               }
+               display_on = TRUE;
+       }
+
+       return 0;
+}
+
+static void tmd20qvga_disp_set_contrast(void)
+{
+#if (defined(TMD20QVGA_LCD_18BPP))
+
+       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0302);
+       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
+       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
+
+#else
+       int newcontrast = 0x46;
+
+       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+
+       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR,
+                       DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP20) |
+                       DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP21) |
+                       DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP22) |
+                       DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP30) |
+                       DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP31) |
+                       DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP32));
+
+       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR,
+                       DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP40) |
+                       DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP41) |
+                       DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP42) |
+                       DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP50) |
+                       DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP51) |
+                       DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP52));
+
+       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+       DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
+
+#endif /* defined(TMD20QVGA_LCD_18BPP) */
+
+}      /* End disp_set_contrast */
+
+void tmd20qvga_disp_clear_screen_area
+    (word start_row, word end_row, word start_column, word end_column) {
+       int32 i;
+
+       /* Clear the display screen */
+       DISP_SET_RECT(start_row, end_row, start_column, end_column);
+       DISP_CMD_OUT(DISP_CMD_RAMWR);
+       i = (end_row - start_row + 1) * (end_column - start_column + 1);
+       for (; i > 0; i--)
+               DISP_DATA_OUT_16TO18BPP(0x0);
+}
+
+static int __init tmd20qvga_probe(struct platform_device *pdev)
+{
+       msm_fb_add_device(pdev);
+
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = tmd20qvga_probe,
+       .driver = {
+               .name   = "ebi2_tmd_qvga",
+       },
+};
+
+static struct msm_fb_panel_data tmd20qvga_panel_data = {
+       .on = tmd20qvga_disp_on,
+       .off = tmd20qvga_disp_off,
+       .set_rect = tmd20qvga_disp_set_rect,
+};
+
+static struct platform_device this_device = {
+       .name   = "ebi2_tmd_qvga",
+       .id     = 0,
+       .dev    = {
+               .platform_data = &tmd20qvga_panel_data,
+       }
+};
+
+static int __init tmd20qvga_init(void)
+{
+       int ret;
+       struct msm_panel_info *pinfo;
+
+       ret = platform_driver_register(&this_driver);
+       if (!ret) {
+               pinfo = &tmd20qvga_panel_data.panel_info;
+               pinfo->xres = 240;
+               pinfo->yres = 320;
+               pinfo->type = EBI2_PANEL;
+               pinfo->pdest = DISPLAY_1;
+               pinfo->wait_cycle = 0x808000;
+#ifdef TMD20QVGA_LCD_18BPP
+               pinfo->bpp = 18;
+#else
+               pinfo->bpp = 16;
+#endif
+               pinfo->fb_num = 2;
+               pinfo->lcd.vsync_enable = TRUE;
+               pinfo->lcd.refx100 = 6000;
+               pinfo->lcd.v_back_porch = 16;
+               pinfo->lcd.v_front_porch = 4;
+               pinfo->lcd.v_pulse_width = 0;
+               pinfo->lcd.hw_vsync_mode = FALSE;
+               pinfo->lcd.vsync_notifier_period = 0;
+
+               ret = platform_device_register(&this_device);
+               if (ret)
+                       platform_driver_unregister(&this_driver);
+       }
+
+       return ret;
+}
+
+module_init(tmd20qvga_init);
diff --git a/drivers/staging/msm/hdmi_sii9022.c b/drivers/staging/msm/hdmi_sii9022.c
new file mode 100644 (file)
index 0000000..6b82b56
--- /dev/null
@@ -0,0 +1,248 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "msm_fb.h"
+
+#define DEVICE_NAME "sii9022"
+#define SII9022_DEVICE_ID   0xB0
+
+struct sii9022_i2c_addr_data{
+       u8 addr;
+       u8 data;
+};
+
+/* video mode data */
+static u8 video_mode_data[] = {
+       0x00,
+       0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
+};
+
+static u8 avi_io_format[] = {
+       0x09,
+       0x00, 0x00,
+};
+
+/* power state */
+static struct sii9022_i2c_addr_data regset0[] = {
+       { 0x60, 0x04 },
+       { 0x63, 0x00 },
+       { 0x1E, 0x00 },
+};
+
+static u8 video_infoframe[] = {
+       0x0C,
+       0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
+       0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
+};
+
+/* configure audio */
+static struct sii9022_i2c_addr_data regset1[] = {
+       { 0x26, 0x90 },
+       { 0x20, 0x90 },
+       { 0x1F, 0x80 },
+       { 0x26, 0x80 },
+       { 0x24, 0x02 },
+       { 0x25, 0x0B },
+       { 0xBC, 0x02 },
+       { 0xBD, 0x24 },
+       { 0xBE, 0x02 },
+};
+
+/* enable audio */
+static u8 misc_infoframe[] = {
+       0xBF,
+       0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+/* set HDMI, active */
+static struct sii9022_i2c_addr_data regset2[] = {
+       { 0x1A, 0x01 },
+       { 0x3D, 0x00 },
+};
+
+static int send_i2c_data(struct i2c_client *client,
+                        struct sii9022_i2c_addr_data *regset,
+                        int size)
+{
+       int i;
+       int rc = 0;
+
+       for (i = 0; i < size; i++) {
+               rc = i2c_smbus_write_byte_data(
+                       client,
+                       regset[i].addr, regset[i].data);
+               if (rc)
+                       break;
+       }
+       return rc;
+}
+
+static int hdmi_sii_enable(struct i2c_client *client)
+{
+       int rc;
+       int retries = 10;
+       int count;
+
+       rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
+       if (rc)
+               goto enable_exit;
+
+       do {
+               msleep(1);
+               rc = i2c_smbus_read_byte_data(client, 0x1B);
+       } while ((rc != SII9022_DEVICE_ID) && retries--);
+
+       if (rc != SII9022_DEVICE_ID)
+               return -ENODEV;
+
+       rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
+       if (rc)
+               goto enable_exit;
+
+       count = ARRAY_SIZE(video_mode_data);
+       rc = i2c_master_send(client, video_mode_data, count);
+       if (rc != count) {
+               rc = -EIO;
+               goto enable_exit;
+       }
+
+       rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
+       if (rc)
+               goto enable_exit;
+       count = ARRAY_SIZE(avi_io_format);
+       rc = i2c_master_send(client, avi_io_format, count);
+       if (rc != count) {
+               rc = -EIO;
+               goto enable_exit;
+       }
+
+       rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
+       if (rc)
+               goto enable_exit;
+
+       count = ARRAY_SIZE(video_infoframe);
+       rc = i2c_master_send(client, video_infoframe, count);
+       if (rc != count) {
+               rc = -EIO;
+               goto enable_exit;
+       }
+
+       rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
+       if (rc)
+               goto enable_exit;
+
+       count = ARRAY_SIZE(misc_infoframe);
+       rc = i2c_master_send(client, misc_infoframe, count);
+       if (rc != count) {
+               rc = -EIO;
+               goto enable_exit;
+       }
+
+       rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
+       if (rc)
+               goto enable_exit;
+
+       return 0;
+enable_exit:
+       printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
+       return rc;
+}
+
+static const struct i2c_device_id hmdi_sii_id[] = {
+       { DEVICE_NAME, 0 },
+       { }
+};
+
+static int hdmi_sii_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       int rc;
+
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
+               return -ENODEV;
+       rc = hdmi_sii_enable(client);
+       return rc;
+}
+
+
+static struct i2c_driver hdmi_sii_i2c_driver = {
+       .driver = {
+               .name = DEVICE_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe = hdmi_sii_probe,
+       .remove =  __exit_p(hdmi_sii_remove),
+       .id_table = hmdi_sii_id,
+};
+
+static int __init hdmi_sii_init(void)
+{
+       int ret;
+       struct msm_panel_info pinfo;
+
+       if (msm_fb_detect_client("hdmi_sii9022"))
+               return 0;
+
+       pinfo.xres = 1280;
+       pinfo.yres = 720;
+       pinfo.type = HDMI_PANEL;
+       pinfo.pdest = DISPLAY_1;
+       pinfo.wait_cycle = 0;
+       pinfo.bpp = 24;
+       pinfo.fb_num = 2;
+       pinfo.clk_rate = 74250000;
+
+       pinfo.lcdc.h_back_porch = 124;
+       pinfo.lcdc.h_front_porch = 110;
+       pinfo.lcdc.h_pulse_width = 136;
+       pinfo.lcdc.v_back_porch = 19;
+       pinfo.lcdc.v_front_porch = 5;
+       pinfo.lcdc.v_pulse_width = 6;
+       pinfo.lcdc.border_clr = 0;
+       pinfo.lcdc.underflow_clr = 0xff;
+       pinfo.lcdc.hsync_skew = 0;
+
+       ret = lcdc_device_register(&pinfo);
+       if (ret) {
+               printk(KERN_ERR "%s: failed to register device\n", __func__);
+               goto init_exit;
+       }
+
+       ret = i2c_add_driver(&hdmi_sii_i2c_driver);
+       if (ret)
+               printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
+
+init_exit:
+       return ret;
+}
+
+static void __exit hdmi_sii_exit(void)
+{
+       i2c_del_driver(&hdmi_sii_i2c_driver);
+}
+
+module_init(hdmi_sii_init);
+module_exit(hdmi_sii_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.1");
+MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
+MODULE_DESCRIPTION("SiI9022 HDMI driver");
+MODULE_ALIAS("platform:hdmi-sii9022");
diff --git a/drivers/staging/msm/lcdc.c b/drivers/staging/msm/lcdc.c
new file mode 100644 (file)
index 0000000..735280a
--- /dev/null
@@ -0,0 +1,239 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos_params.h>
+
+#include "msm_fb.h"
+
+static int lcdc_probe(struct platform_device *pdev);
+static int lcdc_remove(struct platform_device *pdev);
+
+static int lcdc_off(struct platform_device *pdev);
+static int lcdc_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static struct clk *mdp_lcdc_pclk_clk;
+static struct clk *mdp_lcdc_pad_pclk_clk;
+
+int mdp_lcdc_pclk_clk_rate;
+int mdp_lcdc_pad_pclk_clk_rate;
+
+static struct platform_driver lcdc_driver = {
+       .probe = lcdc_probe,
+       .remove = lcdc_remove,
+       .suspend = NULL,
+       .resume = NULL,
+       .shutdown = NULL,
+       .driver = {
+                  .name = "lcdc",
+                  },
+};
+
+static struct lcdc_platform_data *lcdc_pdata;
+
+static int lcdc_off(struct platform_device *pdev)
+{
+       int ret = 0;
+
+       ret = panel_next_off(pdev);
+
+       clk_disable(mdp_lcdc_pclk_clk);
+       clk_disable(mdp_lcdc_pad_pclk_clk);
+
+       if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
+               lcdc_pdata->lcdc_power_save(0);
+
+       if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
+               ret = lcdc_pdata->lcdc_gpio_config(0);
+
+//     pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
+//                                     PM_QOS_DEFAULT_VALUE);
+
+       return ret;
+}
+
+static int lcdc_on(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct msm_fb_data_type *mfd;
+       unsigned long panel_pixclock_freq , pm_qos_freq;
+
+       mfd = platform_get_drvdata(pdev);
+       panel_pixclock_freq = mfd->fbi->var.pixclock;
+
+       if (panel_pixclock_freq > 58000000)
+               /* pm_qos_freq should be in Khz */
+               pm_qos_freq = panel_pixclock_freq / 1000 ;
+       else
+               pm_qos_freq = 58000;
+
+//     pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
+//                                             pm_qos_freq);
+       mfd = platform_get_drvdata(pdev);
+
+       clk_enable(mdp_lcdc_pclk_clk);
+       clk_enable(mdp_lcdc_pad_pclk_clk);
+
+       if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
+               lcdc_pdata->lcdc_power_save(1);
+       if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
+               ret = lcdc_pdata->lcdc_gpio_config(1);
+
+       clk_set_rate(mdp_lcdc_pclk_clk, mfd->fbi->var.pixclock);
+       clk_set_rate(mdp_lcdc_pad_pclk_clk, mfd->fbi->var.pixclock);
+       mdp_lcdc_pclk_clk_rate = clk_get_rate(mdp_lcdc_pclk_clk);
+       mdp_lcdc_pad_pclk_clk_rate = clk_get_rate(mdp_lcdc_pad_pclk_clk);
+
+       ret = panel_next_on(pdev);
+       return ret;
+}
+
+static int lcdc_probe(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+       struct fb_info *fbi;
+       struct platform_device *mdp_dev = NULL;
+       struct msm_fb_panel_data *pdata = NULL;
+       int rc;
+
+       if (pdev->id == 0) {
+               lcdc_pdata = pdev->dev.platform_data;
+               return 0;
+       }
+
+       mfd = platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+               return -ENOMEM;
+
+       mdp_dev = platform_device_alloc("mdp", pdev->id);
+       if (!mdp_dev)
+               return -ENOMEM;
+
+       /*
+        * link to the latest pdev
+        */
+       mfd->pdev = mdp_dev;
+       mfd->dest = DISPLAY_LCDC;
+
+       /*
+        * alloc panel device data
+        */
+       if (platform_device_add_data
+           (mdp_dev, pdev->dev.platform_data,
+            sizeof(struct msm_fb_panel_data))) {
+               printk(KERN_ERR "lcdc_probe: platform_device_add_data failed!\n");
+               platform_device_put(mdp_dev);
+               return -ENOMEM;
+       }
+       /*
+        * data chain
+        */
+       pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data;
+       pdata->on = lcdc_on;
+       pdata->off = lcdc_off;
+       pdata->next = pdev;
+
+       /*
+        * get/set panel specific fb info
+        */
+       mfd->panel_info = pdata->panel_info;
+       mfd->fb_imgType = MDP_RGB_565;
+
+       fbi = mfd->fbi;
+       fbi->var.pixclock = mfd->panel_info.clk_rate;
+       fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
+       fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
+       fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
+       fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
+       fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
+       fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
+
+       /*
+        * set driver data
+        */
+       platform_set_drvdata(mdp_dev, mfd);
+
+       /*
+        * register in mdp driver
+        */
+       rc = platform_device_add(mdp_dev);
+       if (rc)
+               goto lcdc_probe_err;
+
+       pdev_list[pdev_list_cnt++] = pdev;
+               return 0;
+
+lcdc_probe_err:
+       platform_device_put(mdp_dev);
+       return rc;
+}
+
+static int lcdc_remove(struct platform_device *pdev)
+{
+//     pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc");
+       return 0;
+}
+
+static int lcdc_register_driver(void)
+{
+       return platform_driver_register(&lcdc_driver);
+}
+
+static int __init lcdc_driver_init(void)
+{
+       mdp_lcdc_pclk_clk = clk_get(NULL, "mdp_lcdc_pclk_clk");
+       if (IS_ERR(mdp_lcdc_pclk_clk)) {
+               printk(KERN_ERR "error: can't get mdp_lcdc_pclk_clk!\n");
+               return IS_ERR(mdp_lcdc_pclk_clk);
+       }
+       mdp_lcdc_pad_pclk_clk = clk_get(NULL, "mdp_lcdc_pad_pclk_clk");
+       if (IS_ERR(mdp_lcdc_pad_pclk_clk)) {
+               printk(KERN_ERR "error: can't get mdp_lcdc_pad_pclk_clk!\n");
+               return IS_ERR(mdp_lcdc_pad_pclk_clk);
+       }
+//     pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
+//                             PM_QOS_DEFAULT_VALUE);
+       return lcdc_register_driver();
+}
+
+module_init(lcdc_driver_init);
diff --git a/drivers/staging/msm/lcdc_external.c b/drivers/staging/msm/lcdc_external.c
new file mode 100644 (file)
index 0000000..45ff785
--- /dev/null
@@ -0,0 +1,54 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int __init lcdc_external_init(void)
+{
+       int ret;
+       struct msm_panel_info pinfo;
+
+       if (msm_fb_detect_client("lcdc_external"))
+               return 0;
+
+       pinfo.xres = 1280;
+       pinfo.yres = 720;
+       pinfo.type = LCDC_PANEL;
+       pinfo.pdest = DISPLAY_1;
+       pinfo.wait_cycle = 0;
+       pinfo.bpp = 24;
+       pinfo.fb_num = 2;
+       pinfo.clk_rate = 74250000;
+
+       pinfo.lcdc.h_back_porch = 124;
+       pinfo.lcdc.h_front_porch = 110;
+       pinfo.lcdc.h_pulse_width = 136;
+       pinfo.lcdc.v_back_porch = 19;
+       pinfo.lcdc.v_front_porch = 5;
+       pinfo.lcdc.v_pulse_width = 6;
+       pinfo.lcdc.border_clr = 0;      /* blk */
+       pinfo.lcdc.underflow_clr = 0xff;        /* blue */
+       pinfo.lcdc.hsync_skew = 0;
+
+       ret = lcdc_device_register(&pinfo);
+       if (ret)
+               printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+       return ret;
+}
+
+module_init(lcdc_external_init);
diff --git a/drivers/staging/msm/lcdc_gordon.c b/drivers/staging/msm/lcdc_gordon.c
new file mode 100644 (file)
index 0000000..399ec8c
--- /dev/null
@@ -0,0 +1,446 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/delay.h>
+#include <mach/gpio.h>
+#include "msm_fb.h"
+
+/* registers */
+#define GORDON_REG_NOP          0x00
+#define GORDON_REG_IMGCTL1      0x10
+#define GORDON_REG_IMGCTL2      0x11
+#define GORDON_REG_IMGSET1      0x12
+#define GORDON_REG_IMGSET2      0x13
+#define GORDON_REG_IVBP1        0x14
+#define GORDON_REG_IHBP1        0x15
+#define GORDON_REG_IVNUM1       0x16
+#define GORDON_REG_IHNUM1       0x17
+#define GORDON_REG_IVBP2        0x18
+#define GORDON_REG_IHBP2        0x19
+#define GORDON_REG_IVNUM2       0x1A
+#define GORDON_REG_IHNUM2       0x1B
+#define GORDON_REG_LCDIFCTL1    0x30
+#define GORDON_REG_VALTRAN      0x31
+#define GORDON_REG_AVCTL        0x33
+#define GORDON_REG_LCDIFCTL2    0x34
+#define GORDON_REG_LCDIFCTL3    0x35
+#define GORDON_REG_LCDIFSET1    0x36
+#define GORDON_REG_PCCTL        0x3C
+#define GORDON_REG_TPARAM1      0x40
+#define GORDON_REG_TLCDIF1      0x41
+#define GORDON_REG_TSSPB_ST1    0x42
+#define GORDON_REG_TSSPB_ED1    0x43
+#define GORDON_REG_TSCK_ST1     0x44
+#define GORDON_REG_TSCK_WD1     0x45
+#define GORDON_REG_TGSPB_VST1   0x46
+#define GORDON_REG_TGSPB_VED1   0x47
+#define GORDON_REG_TGSPB_CH1    0x48
+#define GORDON_REG_TGCK_ST1     0x49
+#define GORDON_REG_TGCK_ED1     0x4A
+#define GORDON_REG_TPCTL_ST1    0x4B
+#define GORDON_REG_TPCTL_ED1    0x4C
+#define GORDON_REG_TPCHG_ED1    0x4D
+#define GORDON_REG_TCOM_CH1     0x4E
+#define GORDON_REG_THBP1        0x4F
+#define GORDON_REG_TPHCTL1      0x50
+#define GORDON_REG_EVPH1        0x51
+#define GORDON_REG_EVPL1        0x52
+#define GORDON_REG_EVNH1        0x53
+#define GORDON_REG_EVNL1        0x54
+#define GORDON_REG_TBIAS1       0x55
+#define GORDON_REG_TPARAM2      0x56
+#define GORDON_REG_TLCDIF2      0x57
+#define GORDON_REG_TSSPB_ST2    0x58
+#define GORDON_REG_TSSPB_ED2    0x59
+#define GORDON_REG_TSCK_ST2     0x5A
+#define GORDON_REG_TSCK_WD2     0x5B
+#define GORDON_REG_TGSPB_VST2   0x5C
+#define GORDON_REG_TGSPB_VED2   0x5D
+#define GORDON_REG_TGSPB_CH2    0x5E
+#define GORDON_REG_TGCK_ST2     0x5F
+#define GORDON_REG_TGCK_ED2     0x60
+#define GORDON_REG_TPCTL_ST2    0x61
+#define GORDON_REG_TPCTL_ED2    0x62
+#define GORDON_REG_TPCHG_ED2    0x63
+#define GORDON_REG_TCOM_CH2     0x64
+#define GORDON_REG_THBP2        0x65
+#define GORDON_REG_TPHCTL2      0x66
+#define GORDON_REG_POWCTL       0x80
+
+static int lcdc_gordon_panel_off(struct platform_device *pdev);
+
+static int spi_cs;
+static int spi_sclk;
+static int spi_sdo;
+static int spi_sdi;
+static int spi_dac;
+static unsigned char bit_shift[8] = { (1 << 7),        /* MSB */
+       (1 << 6),
+       (1 << 5),
+       (1 << 4),
+       (1 << 3),
+       (1 << 2),
+       (1 << 1),
+       (1 << 0)                               /* LSB */
+};
+
+struct gordon_state_type{
+       boolean disp_initialized;
+       boolean display_on;
+       boolean disp_powered_up;
+};
+
+static struct gordon_state_type gordon_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_gordon_pdata;
+
+static void serigo(uint16 reg, uint8 data)
+{
+       unsigned int tx_val = ((0x00FF & reg) << 8) | data;
+       unsigned char i, val = 0;
+
+       /* Enable the Chip Select */
+       gpio_set_value(spi_cs, 1);
+       udelay(33);
+
+       /* Transmit it in two parts, Higher Byte first, then Lower Byte */
+       val = (unsigned char)((tx_val & 0xFF00) >> 8);
+
+       /* Clock should be Low before entering ! */
+       for (i = 0; i < 8; i++) {
+               /* #1: Drive the Data (High or Low) */
+               if (val & bit_shift[i])
+                       gpio_set_value(spi_sdi, 1);
+               else
+                       gpio_set_value(spi_sdi, 0);
+
+               /* #2: Drive the Clk High and then Low */
+               udelay(33);
+               gpio_set_value(spi_sclk, 1);
+               udelay(33);
+               gpio_set_value(spi_sclk, 0);
+       }
+
+       /* Idle state of SDO (MOSI) is Low */
+       gpio_set_value(spi_sdi, 0);
+       /* ..then Lower Byte */
+       val = (uint8) (tx_val & 0x00FF);
+       /* Before we enter here the Clock should be Low ! */
+
+       for (i = 0; i < 8; i++) {
+               /* #1: Drive the Data (High or Low) */
+               if (val & bit_shift[i])
+                       gpio_set_value(spi_sdi, 1);
+               else
+                       gpio_set_value(spi_sdi, 0);
+
+               /* #2: Drive the Clk High and then Low */
+               udelay(33);
+
+               gpio_set_value(spi_sclk, 1);
+               udelay(33);
+               gpio_set_value(spi_sclk, 0);
+       }
+
+       /* Idle state of SDO (MOSI) is Low */
+       gpio_set_value(spi_sdi, 0);
+
+       /* Now Disable the Chip Select */
+       udelay(33);
+       gpio_set_value(spi_cs, 0);
+}
+
+static void spi_init(void)
+{
+       /* Setting the Default GPIO's */
+       spi_sclk = *(lcdc_gordon_pdata->gpio_num);
+       spi_cs   = *(lcdc_gordon_pdata->gpio_num + 1);
+       spi_sdi  = *(lcdc_gordon_pdata->gpio_num + 2);
+       spi_sdo  = *(lcdc_gordon_pdata->gpio_num + 3);
+
+       /* Set the output so that we dont disturb the slave device */
+       gpio_set_value(spi_sclk, 0);
+       gpio_set_value(spi_sdi, 0);
+
+       /* Set the Chip Select De-asserted */
+       gpio_set_value(spi_cs, 0);
+
+}
+
+static void gordon_disp_powerup(void)
+{
+       if (!gordon_state.disp_powered_up && !gordon_state.display_on) {
+               /* Reset the hardware first */
+               /* Include DAC power up implementation here */
+             gordon_state.disp_powered_up = TRUE;
+       }
+}
+
+static void gordon_init(void)
+{
+       /* Image interface settings */
+       serigo(GORDON_REG_IMGCTL2, 0x00);
+       serigo(GORDON_REG_IMGSET1, 0x00);
+
+       /* Exchange the RGB signal for J510(Softbank mobile) */
+       serigo(GORDON_REG_IMGSET2, 0x12);
+       serigo(GORDON_REG_LCDIFSET1, 0x00);
+
+       /* Pre-charge settings */
+       serigo(GORDON_REG_PCCTL, 0x09);
+       serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+
+       mdelay(1);
+}
+
+static void gordon_disp_on(void)
+{
+       if (gordon_state.disp_powered_up && !gordon_state.display_on) {
+               gordon_init();
+               mdelay(20);
+               /* gordon_dispmode setting */
+               serigo(GORDON_REG_TPARAM1, 0x30);
+               serigo(GORDON_REG_TLCDIF1, 0x00);
+               serigo(GORDON_REG_TSSPB_ST1, 0x8B);
+               serigo(GORDON_REG_TSSPB_ED1, 0x93);
+               serigo(GORDON_REG_TSCK_ST1, 0x88);
+               serigo(GORDON_REG_TSCK_WD1, 0x00);
+               serigo(GORDON_REG_TGSPB_VST1, 0x01);
+               serigo(GORDON_REG_TGSPB_VED1, 0x02);
+               serigo(GORDON_REG_TGSPB_CH1, 0x5E);
+               serigo(GORDON_REG_TGCK_ST1, 0x80);
+               serigo(GORDON_REG_TGCK_ED1, 0x3C);
+               serigo(GORDON_REG_TPCTL_ST1, 0x50);
+               serigo(GORDON_REG_TPCTL_ED1, 0x74);
+               serigo(GORDON_REG_TPCHG_ED1, 0x78);
+               serigo(GORDON_REG_TCOM_CH1, 0x50);
+               serigo(GORDON_REG_THBP1, 0x84);
+               serigo(GORDON_REG_TPHCTL1, 0x00);
+               serigo(GORDON_REG_EVPH1, 0x70);
+               serigo(GORDON_REG_EVPL1, 0x64);
+               serigo(GORDON_REG_EVNH1, 0x56);
+               serigo(GORDON_REG_EVNL1, 0x48);
+               serigo(GORDON_REG_TBIAS1, 0x88);
+
+               /* QVGA settings */
+               serigo(GORDON_REG_TPARAM2, 0x28);
+               serigo(GORDON_REG_TLCDIF2, 0x14);
+               serigo(GORDON_REG_TSSPB_ST2, 0x49);
+               serigo(GORDON_REG_TSSPB_ED2, 0x4B);
+               serigo(GORDON_REG_TSCK_ST2, 0x4A);
+               serigo(GORDON_REG_TSCK_WD2, 0x02);
+               serigo(GORDON_REG_TGSPB_VST2, 0x02);
+               serigo(GORDON_REG_TGSPB_VED2, 0x03);
+               serigo(GORDON_REG_TGSPB_CH2, 0x2F);
+               serigo(GORDON_REG_TGCK_ST2, 0x40);
+               serigo(GORDON_REG_TGCK_ED2, 0x1E);
+               serigo(GORDON_REG_TPCTL_ST2, 0x2C);
+               serigo(GORDON_REG_TPCTL_ED2, 0x3A);
+               serigo(GORDON_REG_TPCHG_ED2, 0x3C);
+               serigo(GORDON_REG_TCOM_CH2, 0x28);
+               serigo(GORDON_REG_THBP2, 0x4D);
+               serigo(GORDON_REG_TPHCTL2, 0x1A);
+
+               /* VGA settings */
+               serigo(GORDON_REG_IVBP1, 0x02);
+               serigo(GORDON_REG_IHBP1, 0x90);
+               serigo(GORDON_REG_IVNUM1, 0xA0);
+               serigo(GORDON_REG_IHNUM1, 0x78);
+
+               /* QVGA settings */
+               serigo(GORDON_REG_IVBP2, 0x02);
+               serigo(GORDON_REG_IHBP2, 0x48);
+               serigo(GORDON_REG_IVNUM2, 0x50);
+               serigo(GORDON_REG_IHNUM2, 0x3C);
+
+               /* Gordon Charge pump settings and ON */
+               serigo(GORDON_REG_POWCTL, 0x03);
+               mdelay(15);
+               serigo(GORDON_REG_POWCTL, 0x07);
+               mdelay(15);
+
+               serigo(GORDON_REG_POWCTL, 0x0F);
+               mdelay(15);
+
+               serigo(GORDON_REG_AVCTL, 0x03);
+               mdelay(15);
+
+               serigo(GORDON_REG_POWCTL, 0x1F);
+               mdelay(15);
+
+               serigo(GORDON_REG_POWCTL, 0x5F);
+               mdelay(15);
+
+               serigo(GORDON_REG_POWCTL, 0x7F);
+               mdelay(15);
+
+               serigo(GORDON_REG_LCDIFCTL1, 0x02);
+               mdelay(15);
+
+               serigo(GORDON_REG_IMGCTL1, 0x00);
+               mdelay(15);
+
+               serigo(GORDON_REG_LCDIFCTL3, 0x00);
+               mdelay(15);
+
+               serigo(GORDON_REG_VALTRAN, 0x01);
+               mdelay(15);
+
+               serigo(GORDON_REG_LCDIFCTL1, 0x03);
+               mdelay(1);
+               gordon_state.display_on = TRUE;
+       }
+}
+
+static int lcdc_gordon_panel_on(struct platform_device *pdev)
+{
+       if (!gordon_state.disp_initialized) {
+               /* Configure reset GPIO that drives DAC */
+               lcdc_gordon_pdata->panel_config_gpio(1);
+               spi_dac = *(lcdc_gordon_pdata->gpio_num + 4);
+               gpio_set_value(spi_dac, 0);
+               udelay(15);
+               gpio_set_value(spi_dac, 1);
+               spi_init();     /* LCD needs SPI */
+               gordon_disp_powerup();
+               gordon_disp_on();
+               gordon_state.disp_initialized = TRUE;
+       }
+       return 0;
+}
+
+static int lcdc_gordon_panel_off(struct platform_device *pdev)
+{
+       if (gordon_state.disp_powered_up && gordon_state.display_on) {
+               serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+               serigo(GORDON_REG_VALTRAN, 0x01);
+               serigo(GORDON_REG_LCDIFCTL1, 0x02);
+               serigo(GORDON_REG_LCDIFCTL3, 0x01);
+               mdelay(20);
+               serigo(GORDON_REG_VALTRAN, 0x01);
+               serigo(GORDON_REG_IMGCTL1, 0x01);
+               serigo(GORDON_REG_LCDIFCTL1, 0x00);
+               mdelay(20);
+
+               serigo(GORDON_REG_POWCTL, 0x1F);
+               mdelay(40);
+
+               serigo(GORDON_REG_POWCTL, 0x07);
+               mdelay(40);
+
+               serigo(GORDON_REG_POWCTL, 0x03);
+               mdelay(40);
+
+               serigo(GORDON_REG_POWCTL, 0x00);
+               mdelay(40);
+               lcdc_gordon_pdata->panel_config_gpio(0);
+               gordon_state.display_on = FALSE;
+               gordon_state.disp_initialized = FALSE;
+       }
+       return 0;
+}
+
+static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd)
+{
+               int bl_level = mfd->bl_level;
+
+               if (bl_level <= 1) {
+                       /* keep back light OFF */
+                       serigo(GORDON_REG_LCDIFCTL2, 0x0B);
+                       udelay(15);
+                       serigo(GORDON_REG_VALTRAN, 0x01);
+               } else {
+                       /* keep back light ON */
+                       serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+                       udelay(15);
+                       serigo(GORDON_REG_VALTRAN, 0x01);
+               }
+}
+
+static int __init gordon_probe(struct platform_device *pdev)
+{
+       if (pdev->id == 0) {
+               lcdc_gordon_pdata = pdev->dev.platform_data;
+               return 0;
+       }
+       msm_fb_add_device(pdev);
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = gordon_probe,
+       .driver = {
+               .name   = "lcdc_gordon_vga",
+       },
+};
+
+static struct msm_fb_panel_data gordon_panel_data = {
+       .on = lcdc_gordon_panel_on,
+       .off = lcdc_gordon_panel_off,
+       .set_backlight = lcdc_gordon_set_backlight,
+};
+
+static struct platform_device this_device = {
+       .name   = "lcdc_gordon_vga",
+       .id     = 1,
+       .dev    = {
+               .platform_data = &gordon_panel_data,
+       }
+};
+
+static int __init lcdc_gordon_panel_init(void)
+{
+       int ret;
+       struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+       if (msm_fb_detect_client("lcdc_gordon_vga"))
+               return 0;
+#endif
+       ret = platform_driver_register(&this_driver);
+       if (ret)
+               return ret;
+
+       pinfo = &gordon_panel_data.panel_info;
+       pinfo->xres = 480;
+       pinfo->yres = 640;
+       pinfo->type = LCDC_PANEL;
+       pinfo->pdest = DISPLAY_1;
+       pinfo->wait_cycle = 0;
+       pinfo->bpp = 24;
+       pinfo->fb_num = 2;
+       pinfo->clk_rate = 24500000;
+       pinfo->bl_max = 4;
+       pinfo->bl_min = 1;
+
+       pinfo->lcdc.h_back_porch = 84;
+       pinfo->lcdc.h_front_porch = 33;
+       pinfo->lcdc.h_pulse_width = 60;
+       pinfo->lcdc.v_back_porch = 0;
+       pinfo->lcdc.v_front_porch = 2;
+       pinfo->lcdc.v_pulse_width = 2;
+       pinfo->lcdc.border_clr = 0;     /* blk */
+       pinfo->lcdc.underflow_clr = 0xff;       /* blue */
+       pinfo->lcdc.hsync_skew = 0;
+
+       ret = platform_device_register(&this_device);
+       if (ret)
+               platform_driver_unregister(&this_driver);
+
+       return ret;
+}
+
+module_init(lcdc_gordon_panel_init);
diff --git a/drivers/staging/msm/lcdc_grapefruit.c b/drivers/staging/msm/lcdc_grapefruit.c
new file mode 100644 (file)
index 0000000..7284649
--- /dev/null
@@ -0,0 +1,60 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+#include "mddihosti.h"
+#endif
+
+static int __init lcdc_grapefruit_init(void)
+{
+       int ret;
+       struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+       if (msm_fb_detect_client("lcdc_grapefruit_vga"))
+               return 0;
+#endif
+
+       pinfo.xres = 1024;
+       pinfo.yres = 600;
+       pinfo.type = LCDC_PANEL;
+       pinfo.pdest = DISPLAY_1;
+       pinfo.wait_cycle = 0;
+       pinfo.bpp = 18;
+       pinfo.fb_num = 2;
+       pinfo.clk_rate = 40000000;
+
+       pinfo.lcdc.h_back_porch = 88;
+       pinfo.lcdc.h_front_porch = 40;
+       pinfo.lcdc.h_pulse_width = 128;
+       pinfo.lcdc.v_back_porch = 23;
+       pinfo.lcdc.v_front_porch = 1;
+       pinfo.lcdc.v_pulse_width = 4;
+       pinfo.lcdc.border_clr = 0;      /* blk */
+       pinfo.lcdc.underflow_clr = 0xff;        /* blue */
+       pinfo.lcdc.hsync_skew = 0;
+
+       ret = lcdc_device_register(&pinfo);
+       if (ret)
+               printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+       return ret;
+}
+
+module_init(lcdc_grapefruit_init);
diff --git a/drivers/staging/msm/lcdc_panel.c b/drivers/staging/msm/lcdc_panel.c
new file mode 100644 (file)
index 0000000..b40974e
--- /dev/null
@@ -0,0 +1,88 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int lcdc_panel_on(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static int lcdc_panel_off(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static int __init lcdc_panel_probe(struct platform_device *pdev)
+{
+       msm_fb_add_device(pdev);
+
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = lcdc_panel_probe,
+       .driver = {
+               .name   = "lcdc_panel",
+       },
+};
+
+static struct msm_fb_panel_data lcdc_panel_data = {
+       .on = lcdc_panel_on,
+       .off = lcdc_panel_off,
+};
+
+static int lcdc_dev_id;
+
+int lcdc_device_register(struct msm_panel_info *pinfo)
+{
+       struct platform_device *pdev = NULL;
+       int ret;
+
+       pdev = platform_device_alloc("lcdc_panel", ++lcdc_dev_id);
+       if (!pdev)
+               return -ENOMEM;
+
+       lcdc_panel_data.panel_info = *pinfo;
+       ret = platform_device_add_data(pdev, &lcdc_panel_data,
+               sizeof(lcdc_panel_data));
+       if (ret) {
+               printk(KERN_ERR
+                 "%s: platform_device_add_data failed!\n", __func__);
+               goto err_device_put;
+       }
+
+       ret = platform_device_add(pdev);
+       if (ret) {
+               printk(KERN_ERR
+                 "%s: platform_device_register failed!\n", __func__);
+               goto err_device_put;
+       }
+
+       return 0;
+
+err_device_put:
+       platform_device_put(pdev);
+       return ret;
+}
+
+static int __init lcdc_panel_init(void)
+{
+       return platform_driver_register(&this_driver);
+}
+
+module_init(lcdc_panel_init);
diff --git a/drivers/staging/msm/lcdc_prism.c b/drivers/staging/msm/lcdc_prism.c
new file mode 100644 (file)
index 0000000..d102c98
--- /dev/null
@@ -0,0 +1,64 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+#include "mddihosti.h"
+#endif
+
+static int __init lcdc_prism_init(void)
+{
+       int ret;
+       struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+       ret = msm_fb_detect_client("lcdc_prism_wvga");
+       if (ret == -ENODEV)
+               return 0;
+
+       if (ret && (mddi_get_client_id() != 0))
+               return 0;
+#endif
+
+       pinfo.xres = 800;
+       pinfo.yres = 480;
+       pinfo.type = LCDC_PANEL;
+       pinfo.pdest = DISPLAY_1;
+       pinfo.wait_cycle = 0;
+       pinfo.bpp = 24;
+       pinfo.fb_num = 2;
+       pinfo.clk_rate = 38460000;
+
+       pinfo.lcdc.h_back_porch = 21;
+       pinfo.lcdc.h_front_porch = 81;
+       pinfo.lcdc.h_pulse_width = 60;
+       pinfo.lcdc.v_back_porch = 18;
+       pinfo.lcdc.v_front_porch = 27;
+       pinfo.lcdc.v_pulse_width = 2;
+       pinfo.lcdc.border_clr = 0;      /* blk */
+       pinfo.lcdc.underflow_clr = 0xff;        /* blue */
+       pinfo.lcdc.hsync_skew = 0;
+
+       ret = lcdc_device_register(&pinfo);
+       if (ret)
+               printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+       return ret;
+}
+
+module_init(lcdc_prism_init);
diff --git a/drivers/staging/msm/lcdc_sharp_wvga_pt.c b/drivers/staging/msm/lcdc_sharp_wvga_pt.c
new file mode 100644 (file)
index 0000000..1f08cf9
--- /dev/null
@@ -0,0 +1,290 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/delay.h>
+#ifdef CONFIG_ARCH_MSM7X30
+#include <linux/mfd/pmic8058.h>
+#endif
+#include <mach/gpio.h>
+#include "msm_fb.h"
+
+static int lcdc_sharp_panel_off(struct platform_device *pdev);
+
+static int spi_cs;
+static int spi_sclk;
+static int spi_mosi;
+static int spi_miso;
+static unsigned char bit_shift[8] = { (1 << 7),        /* MSB */
+       (1 << 6),
+       (1 << 5),
+       (1 << 4),
+       (1 << 3),
+       (1 << 2),
+       (1 << 1),
+       (1 << 0)                               /* LSB */
+};
+
+struct sharp_state_type {
+       boolean disp_initialized;
+       boolean display_on;
+       boolean disp_powered_up;
+};
+
+struct sharp_spi_data {
+       u8 addr;
+       u8 data;
+};
+
+static struct sharp_spi_data init_sequence[] = {
+       {  15, 0x01 },
+       {   5, 0x01 },
+       {   7, 0x10 },
+       {   9, 0x1E },
+       {  10, 0x04 },
+       {  17, 0xFF },
+       {  21, 0x8A },
+       {  22, 0x00 },
+       {  23, 0x82 },
+       {  24, 0x24 },
+       {  25, 0x22 },
+       {  26, 0x6D },
+       {  27, 0xEB },
+       {  28, 0xB9 },
+       {  29, 0x3A },
+       {  49, 0x1A },
+       {  50, 0x16 },
+       {  51, 0x05 },
+       {  55, 0x7F },
+       {  56, 0x15 },
+       {  57, 0x7B },
+       {  60, 0x05 },
+       {  61, 0x0C },
+       {  62, 0x80 },
+       {  63, 0x00 },
+       {  92, 0x90 },
+       {  97, 0x01 },
+       {  98, 0xFF },
+       { 113, 0x11 },
+       { 114, 0x02 },
+       { 115, 0x08 },
+       { 123, 0xAB },
+       { 124, 0x04 },
+       {   6, 0x02 },
+       { 133, 0x00 },
+       { 134, 0xFE },
+       { 135, 0x22 },
+       { 136, 0x0B },
+       { 137, 0xFF },
+       { 138, 0x0F },
+       { 139, 0x00 },
+       { 140, 0xFE },
+       { 141, 0x22 },
+       { 142, 0x0B },
+       { 143, 0xFF },
+       { 144, 0x0F },
+       { 145, 0x00 },
+       { 146, 0xFE },
+       { 147, 0x22 },
+       { 148, 0x0B },
+       { 149, 0xFF },
+       { 150, 0x0F },
+       { 202, 0x30 },
+       {  30, 0x01 },
+       {   4, 0x01 },
+       {  31, 0x41 },
+};
+
+static struct sharp_state_type sharp_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_sharp_pdata;
+
+static void sharp_spi_write_byte(u8 val)
+{
+       int i;
+
+       /* Clock should be Low before entering */
+       for (i = 0; i < 8; i++) {
+               /* #1: Drive the Data (High or Low) */
+               if (val & bit_shift[i])
+                       gpio_set_value(spi_mosi, 1);
+               else
+                       gpio_set_value(spi_mosi, 0);
+
+               /* #2: Drive the Clk High and then Low */
+               gpio_set_value(spi_sclk, 1);
+               gpio_set_value(spi_sclk, 0);
+       }
+}
+
+static void serigo(u8 reg, u8 data)
+{
+       /* Enable the Chip Select - low */
+       gpio_set_value(spi_cs, 0);
+       udelay(1);
+
+       /* Transmit register address first, then data */
+       sharp_spi_write_byte(reg);
+
+       /* Idle state of MOSI is Low */
+       gpio_set_value(spi_mosi, 0);
+       udelay(1);
+       sharp_spi_write_byte(data);
+
+       gpio_set_value(spi_mosi, 0);
+       gpio_set_value(spi_cs, 1);
+}
+
+static void sharp_spi_init(void)
+{
+       spi_sclk = *(lcdc_sharp_pdata->gpio_num);
+       spi_cs   = *(lcdc_sharp_pdata->gpio_num + 1);
+       spi_mosi = *(lcdc_sharp_pdata->gpio_num + 2);
+       spi_miso = *(lcdc_sharp_pdata->gpio_num + 3);
+
+       /* Set the output so that we don't disturb the slave device */
+       gpio_set_value(spi_sclk, 0);
+       gpio_set_value(spi_mosi, 0);
+
+       /* Set the Chip Select deasserted (active low) */
+       gpio_set_value(spi_cs, 1);
+}
+
+static void sharp_disp_powerup(void)
+{
+       if (!sharp_state.disp_powered_up && !sharp_state.display_on)
+               sharp_state.disp_powered_up = TRUE;
+}
+
+static void sharp_disp_on(void)
+{
+       int i;
+
+       if (sharp_state.disp_powered_up && !sharp_state.display_on) {
+               for (i = 0; i < ARRAY_SIZE(init_sequence); i++) {
+                       serigo(init_sequence[i].addr,
+                              init_sequence[i].data);
+               }
+               mdelay(10);
+               serigo(31, 0xC1);
+               mdelay(10);
+               serigo(31, 0xD9);
+               serigo(31, 0xDF);
+
+               sharp_state.display_on = TRUE;
+       }
+}
+
+static int lcdc_sharp_panel_on(struct platform_device *pdev)
+{
+       if (!sharp_state.disp_initialized) {
+               lcdc_sharp_pdata->panel_config_gpio(1);
+               sharp_spi_init();
+               sharp_disp_powerup();
+               sharp_disp_on();
+               sharp_state.disp_initialized = TRUE;
+       }
+       return 0;
+}
+
+static int lcdc_sharp_panel_off(struct platform_device *pdev)
+{
+       if (sharp_state.disp_powered_up && sharp_state.display_on) {
+               serigo(4, 0x00);
+               mdelay(40);
+               serigo(31, 0xC1);
+               mdelay(40);
+               serigo(31, 0x00);
+               mdelay(100);
+               sharp_state.display_on = FALSE;
+               sharp_state.disp_initialized = FALSE;
+       }
+       return 0;
+}
+
+static int __init sharp_probe(struct platform_device *pdev)
+{
+       if (pdev->id == 0) {
+               lcdc_sharp_pdata = pdev->dev.platform_data;
+               return 0;
+       }
+       msm_fb_add_device(pdev);
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = sharp_probe,
+       .driver = {
+               .name   = "lcdc_sharp_wvga",
+       },
+};
+
+static struct msm_fb_panel_data sharp_panel_data = {
+       .on = lcdc_sharp_panel_on,
+       .off = lcdc_sharp_panel_off,
+};
+
+static struct platform_device this_device = {
+       .name   = "lcdc_sharp_wvga",
+       .id     = 1,
+       .dev    = {
+               .platform_data = &sharp_panel_data,
+       }
+};
+
+static int __init lcdc_sharp_panel_init(void)
+{
+       int ret;
+       struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+       if (msm_fb_detect_client("lcdc_sharp_wvga_pt"))
+               return 0;
+#endif
+
+       ret = platform_driver_register(&this_driver);
+       if (ret)
+               return ret;
+
+       pinfo = &sharp_panel_data.panel_info;
+       pinfo->xres = 480;
+       pinfo->yres = 800;
+       pinfo->type = LCDC_PANEL;
+       pinfo->pdest = DISPLAY_1;
+       pinfo->wait_cycle = 0;
+       pinfo->bpp = 18;
+       pinfo->fb_num = 2;
+       pinfo->clk_rate = 24500000;
+       pinfo->bl_max = 4;
+       pinfo->bl_min = 1;
+
+       pinfo->lcdc.h_back_porch = 20;
+       pinfo->lcdc.h_front_porch = 10;
+       pinfo->lcdc.h_pulse_width = 10;
+       pinfo->lcdc.v_back_porch = 2;
+       pinfo->lcdc.v_front_porch = 2;
+       pinfo->lcdc.v_pulse_width = 2;
+       pinfo->lcdc.border_clr = 0;
+       pinfo->lcdc.underflow_clr = 0xff;
+       pinfo->lcdc.hsync_skew = 0;
+
+       ret = platform_device_register(&this_device);
+       if (ret)
+               platform_driver_unregister(&this_driver);
+
+       return ret;
+}
+
+module_init(lcdc_sharp_panel_init);
diff --git a/drivers/staging/msm/lcdc_st15.c b/drivers/staging/msm/lcdc_st15.c
new file mode 100644 (file)
index 0000000..fed8278
--- /dev/null
@@ -0,0 +1,237 @@
+/* Copyright (c) 2010, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "msm_fb.h"
+
+#define DEVICE_NAME "sii9022"
+#define SII9022_DEVICE_ID   0xB0
+
+struct sii9022_i2c_addr_data{
+       u8 addr;
+       u8 data;
+};
+
+/* video mode data */
+static u8 video_mode_data[] = {
+       0x00,
+       0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
+};
+
+static u8 avi_io_format[] = {
+       0x09,
+       0x00, 0x00,
+};
+
+/* power state */
+static struct sii9022_i2c_addr_data regset0[] = {
+       { 0x60, 0x04 },
+       { 0x63, 0x00 },
+       { 0x1E, 0x00 },
+};
+
+static u8 video_infoframe[] = {
+       0x0C,
+       0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
+       0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
+};
+
+/* configure audio */
+static struct sii9022_i2c_addr_data regset1[] = {
+       { 0x26, 0x90 },
+       { 0x20, 0x90 },
+       { 0x1F, 0x80 },
+       { 0x26, 0x80 },
+       { 0x24, 0x02 },
+       { 0x25, 0x0B },
+       { 0xBC, 0x02 },
+       { 0xBD, 0x24 },
+       { 0xBE, 0x02 },
+};
+
+/* enable audio */
+static u8 misc_infoframe[] = {
+       0xBF,
+       0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+/* set HDMI, active */
+static struct sii9022_i2c_addr_data regset2[] = {
+       { 0x1A, 0x01 },
+       { 0x3D, 0x00 },
+};
+
+static int send_i2c_data(struct i2c_client *client,
+                        struct sii9022_i2c_addr_data *regset,
+                        int size)
+{
+       int i;
+       int rc = 0;
+
+       for (i = 0; i < size; i++) {
+               rc = i2c_smbus_write_byte_data(
+                       client,
+                       regset[i].addr, regset[i].data);
+               if (rc)
+                       break;
+       }
+       return rc;
+}
+
+static int hdmi_sii_enable(struct i2c_client *client)
+{
+       int rc;
+       int retries = 10;
+       int count;
+
+       rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
+       if (rc)
+               goto enable_exit;
+
+       do {
+               msleep(1);
+               rc = i2c_smbus_read_byte_data(client, 0x1B);
+       } while ((rc != SII9022_DEVICE_ID) && retries--);
+
+       if (rc != SII9022_DEVICE_ID)
+               return -ENODEV;
+
+       rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
+       if (rc)
+               goto enable_exit;
+
+       count = ARRAY_SIZE(video_mode_data);
+       rc = i2c_master_send(client, video_mode_data, count);
+       if (rc != count) {
+               rc = -EIO;
+               goto enable_exit;
+       }
+
+       rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
+       if (rc)
+               goto enable_exit;
+       count = ARRAY_SIZE(avi_io_format);
+       rc = i2c_master_send(client, avi_io_format, count);
+       if (rc != count) {
+               rc = -EIO;
+               goto enable_exit;
+       }
+
+       rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
+       if (rc)
+               goto enable_exit;
+
+       count = ARRAY_SIZE(video_infoframe);
+       rc = i2c_master_send(client, video_infoframe, count);
+       if (rc != count) {
+               rc = -EIO;
+               goto enable_exit;
+       }
+
+       rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
+       if (rc)
+               goto enable_exit;
+
+       count = ARRAY_SIZE(misc_infoframe);
+       rc = i2c_master_send(client, misc_infoframe, count);
+       if (rc != count) {
+               rc = -EIO;
+               goto enable_exit;
+       }
+
+       rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
+       if (rc)
+               goto enable_exit;
+
+       return 0;
+enable_exit:
+       printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
+       return rc;
+}
+
+static const struct i2c_device_id hmdi_sii_id[] = {
+       { DEVICE_NAME, 0 },
+       { }
+};
+
+static int hdmi_sii_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       int rc;
+
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
+               return -ENODEV;
+       rc = hdmi_sii_enable(client);
+       return rc;
+}
+
+
+static struct i2c_driver hdmi_sii_i2c_driver = {
+       .driver = {
+               .name = DEVICE_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe = hdmi_sii_probe,
+       .remove =  __exit_p(hdmi_sii_remove),
+       .id_table = hmdi_sii_id,
+};
+
+static int __init lcdc_st15_init(void)
+{
+       int ret;
+       struct msm_panel_info pinfo;
+
+       if (msm_fb_detect_client("lcdc_st15"))
+               return 0;
+
+       pinfo.xres = 1366;
+       pinfo.yres = 768;
+       pinfo.type = LCDC_PANEL;
+       pinfo.pdest = DISPLAY_1;
+       pinfo.wait_cycle = 0;
+       pinfo.bpp = 24;
+       pinfo.fb_num = 2;
+       pinfo.clk_rate = 74250000;
+
+       pinfo.lcdc.h_back_porch = 120;
+       pinfo.lcdc.h_front_porch = 20;
+       pinfo.lcdc.h_pulse_width = 40;
+       pinfo.lcdc.v_back_porch = 25;
+       pinfo.lcdc.v_front_porch = 1;
+       pinfo.lcdc.v_pulse_width = 7;
+       pinfo.lcdc.border_clr = 0;      /* blk */
+       pinfo.lcdc.underflow_clr = 0xff;        /* blue */
+       pinfo.lcdc.hsync_skew = 0;
+
+       ret = lcdc_device_register(&pinfo);
+       if (ret) {
+               printk(KERN_ERR "%s: failed to register device!\n", __func__);
+               goto init_exit;
+       }
+
+       ret = i2c_add_driver(&hdmi_sii_i2c_driver);
+       if (ret)
+               printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
+
+init_exit:
+       return ret;
+}
+
+module_init(lcdc_st15_init);
diff --git a/drivers/staging/msm/lcdc_st1_wxga.c b/drivers/staging/msm/lcdc_st1_wxga.c
new file mode 100644 (file)
index 0000000..7376001
--- /dev/null
@@ -0,0 +1,54 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int __init lcdc_st1_wxga_init(void)
+{
+       int ret;
+       struct msm_panel_info pinfo;
+
+       if (msm_fb_detect_client("lcdc_st1_wxga"))
+               return 0;
+
+       pinfo.xres = 1280;
+       pinfo.yres = 720;
+       pinfo.type = LCDC_PANEL;
+       pinfo.pdest = DISPLAY_1;
+       pinfo.wait_cycle = 0;
+       pinfo.bpp = 18;
+       pinfo.fb_num = 2;
+       pinfo.clk_rate = 74250000;
+
+       pinfo.lcdc.h_back_porch = 124;
+       pinfo.lcdc.h_front_porch = 110;
+       pinfo.lcdc.h_pulse_width = 136;
+       pinfo.lcdc.v_back_porch = 19;
+       pinfo.lcdc.v_front_porch = 5;
+       pinfo.lcdc.v_pulse_width = 6;
+       pinfo.lcdc.border_clr = 0;      /* blk */
+       pinfo.lcdc.underflow_clr = 0xff;        /* blue */
+       pinfo.lcdc.hsync_skew = 0;
+
+       ret = lcdc_device_register(&pinfo);
+       if (ret)
+               printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+       return ret;
+}
+
+module_init(lcdc_st1_wxga_init);
diff --git a/drivers/staging/msm/lcdc_toshiba_wvga_pt.c b/drivers/staging/msm/lcdc_toshiba_wvga_pt.c
new file mode 100644 (file)
index 0000000..864d7c1
--- /dev/null
@@ -0,0 +1,374 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <mach/gpio.h>
+#include <mach/pmic.h>
+#include "msm_fb.h"
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+#include "mddihosti.h"
+#endif
+
+static int spi_cs;
+static int spi_sclk;
+static int spi_mosi;
+static int spi_miso;
+
+struct toshiba_state_type{
+       boolean disp_initialized;
+       boolean display_on;
+       boolean disp_powered_up;
+};
+
+static struct toshiba_state_type toshiba_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_toshiba_pdata;
+
+static void toshiba_spi_write_byte(char dc, uint8 data)
+{
+       uint32 bit;
+       int bnum;
+
+       gpio_set_value(spi_sclk, 0); /* clk low */
+       /* dc: 0 for command, 1 for parameter */
+       gpio_set_value(spi_mosi, dc);
+       udelay(1);      /* at least 20 ns */
+       gpio_set_value(spi_sclk, 1); /* clk high */
+       udelay(1);      /* at least 20 ns */
+       bnum = 8;       /* 8 data bits */
+       bit = 0x80;
+       while (bnum) {
+               gpio_set_value(spi_sclk, 0); /* clk low */
+               if (data & bit)
+                       gpio_set_value(spi_mosi, 1);
+               else
+                       gpio_set_value(spi_mosi, 0);
+               udelay(1);
+               gpio_set_value(spi_sclk, 1); /* clk high */
+               udelay(1);
+               bit >>= 1;
+               bnum--;
+       }
+}
+
+static void toshiba_spi_write(char cmd, uint32 data, int num)
+{
+       char *bp;
+
+       gpio_set_value(spi_cs, 1);      /* cs high */
+
+       /* command byte first */
+       toshiba_spi_write_byte(0, cmd);
+
+       /* followed by parameter bytes */
+       if (num) {
+               bp = (char *)&data;;
+               bp += (num - 1);
+               while (num) {
+                       toshiba_spi_write_byte(1, *bp);
+                       num--;
+                       bp--;
+               }
+       }
+
+       gpio_set_value(spi_cs, 0);      /* cs low */
+       udelay(1);
+}
+
+void toshiba_spi_read_bytes(char cmd, uint32 *data, int num)
+{
+       uint32 dbit, bits;
+       int bnum;
+
+       gpio_set_value(spi_cs, 1);      /* cs high */
+
+       /* command byte first */
+       toshiba_spi_write_byte(0, cmd);
+
+       if (num > 1) {
+               /* extra dc bit */
+               gpio_set_value(spi_sclk, 0); /* clk low */
+               udelay(1);
+               dbit = gpio_get_value(spi_miso);/* dc bit */
+               udelay(1);
+               gpio_set_value(spi_sclk, 1); /* clk high */
+       }
+
+       /* followed by data bytes */
+       bnum = num * 8; /* number of bits */
+       bits = 0;
+       while (bnum) {
+               bits <<= 1;
+               gpio_set_value(spi_sclk, 0); /* clk low */
+               udelay(1);
+               dbit = gpio_get_value(spi_miso);
+               udelay(1);
+               gpio_set_value(spi_sclk, 1); /* clk high */
+               bits |= dbit;
+               bnum--;
+       }
+
+       *data = bits;
+
+       udelay(1);
+       gpio_set_value(spi_cs, 0);      /* cs low */
+       udelay(1);
+}
+
+static void spi_pin_assign(void)
+{
+       /* Setting the Default GPIO's */
+       spi_sclk = *(lcdc_toshiba_pdata->gpio_num);
+       spi_cs   = *(lcdc_toshiba_pdata->gpio_num + 1);
+       spi_mosi  = *(lcdc_toshiba_pdata->gpio_num + 2);
+       spi_miso  = *(lcdc_toshiba_pdata->gpio_num + 3);
+}
+
+static void toshiba_disp_powerup(void)
+{
+       if (!toshiba_state.disp_powered_up && !toshiba_state.display_on) {
+               /* Reset the hardware first */
+               /* Include DAC power up implementation here */
+             toshiba_state.disp_powered_up = TRUE;
+       }
+}
+
+static void toshiba_disp_on(void)
+{
+       uint32  data;
+
+       gpio_set_value(spi_cs, 0);      /* low */
+       gpio_set_value(spi_sclk, 1);    /* high */
+       gpio_set_value(spi_mosi, 0);
+       gpio_set_value(spi_miso, 0);
+
+       if (toshiba_state.disp_powered_up && !toshiba_state.display_on) {
+               toshiba_spi_write(0, 0, 0);
+               mdelay(7);
+               toshiba_spi_write(0, 0, 0);
+               mdelay(7);
+               toshiba_spi_write(0, 0, 0);
+               mdelay(7);
+               toshiba_spi_write(0xba, 0x11, 1);
+               toshiba_spi_write(0x36, 0x00, 1);
+               mdelay(1);
+               toshiba_spi_write(0x3a, 0x60, 1);
+               toshiba_spi_write(0xb1, 0x5d, 1);
+               mdelay(1);
+               toshiba_spi_write(0xb2, 0x33, 1);
+               toshiba_spi_write(0xb3, 0x22, 1);
+               mdelay(1);
+               toshiba_spi_write(0xb4, 0x02, 1);
+               toshiba_spi_write(0xb5, 0x1e, 1); /* vcs -- adjust brightness */
+               mdelay(1);
+               toshiba_spi_write(0xb6, 0x27, 1);
+               toshiba_spi_write(0xb7, 0x03, 1);
+               mdelay(1);
+               toshiba_spi_write(0xb9, 0x24, 1);
+               toshiba_spi_write(0xbd, 0xa1, 1);
+               mdelay(1);
+               toshiba_spi_write(0xbb, 0x00, 1);
+               toshiba_spi_write(0xbf, 0x01, 1);
+               mdelay(1);
+               toshiba_spi_write(0xbe, 0x00, 1);
+               toshiba_spi_write(0xc0, 0x11, 1);
+               mdelay(1);
+               toshiba_spi_write(0xc1, 0x11, 1);
+               toshiba_spi_write(0xc2, 0x11, 1);
+               mdelay(1);
+               toshiba_spi_write(0xc3, 0x3232, 2);
+               mdelay(1);
+               toshiba_spi_write(0xc4, 0x3232, 2);
+               mdelay(1);
+               toshiba_spi_write(0xc5, 0x3232, 2);
+               mdelay(1);
+               toshiba_spi_write(0xc6, 0x3232, 2);
+               mdelay(1);
+               toshiba_spi_write(0xc7, 0x6445, 2);
+               mdelay(1);
+               toshiba_spi_write(0xc8, 0x44, 1);
+               toshiba_spi_write(0xc9, 0x52, 1);
+               mdelay(1);
+               toshiba_spi_write(0xca, 0x00, 1);
+               mdelay(1);
+               toshiba_spi_write(0xec, 0x02a4, 2);     /* 0x02a4 */
+               mdelay(1);
+               toshiba_spi_write(0xcf, 0x01, 1);
+               mdelay(1);
+               toshiba_spi_write(0xd0, 0xc003, 2);     /* c003 */
+               mdelay(1);
+               toshiba_spi_write(0xd1, 0x01, 1);
+               mdelay(1);
+               toshiba_spi_write(0xd2, 0x0028, 2);
+               mdelay(1);
+               toshiba_spi_write(0xd3, 0x0028, 2);
+               mdelay(1);
+               toshiba_spi_write(0xd4, 0x26a4, 2);
+               mdelay(1);
+               toshiba_spi_write(0xd5, 0x20, 1);
+               mdelay(1);
+               toshiba_spi_write(0xef, 0x3200, 2);
+               mdelay(32);
+               toshiba_spi_write(0xbc, 0x80, 1);       /* wvga pass through */
+               toshiba_spi_write(0x3b, 0x00, 1);
+               mdelay(1);
+               toshiba_spi_write(0xb0, 0x16, 1);
+               mdelay(1);
+               toshiba_spi_write(0xb8, 0xfff5, 2);
+               mdelay(1);
+               toshiba_spi_write(0x11, 0, 0);
+               mdelay(5);
+               toshiba_spi_write(0x29, 0, 0);
+               mdelay(5);
+               toshiba_state.display_on = TRUE;
+       }
+
+       data = 0;
+       toshiba_spi_read_bytes(0x04, &data, 3);
+       printk(KERN_INFO "toshiba_disp_on: id=%x\n", data);
+
+}
+
+static int lcdc_toshiba_panel_on(struct platform_device *pdev)
+{
+       if (!toshiba_state.disp_initialized) {
+               /* Configure reset GPIO that drives DAC */
+               if (lcdc_toshiba_pdata->panel_config_gpio)
+                       lcdc_toshiba_pdata->panel_config_gpio(1);
+               toshiba_disp_powerup();
+               toshiba_disp_on();
+               toshiba_state.disp_initialized = TRUE;
+       }
+       return 0;
+}
+
+static int lcdc_toshiba_panel_off(struct platform_device *pdev)
+{
+       if (toshiba_state.disp_powered_up && toshiba_state.display_on) {
+               /* Main panel power off (Deep standby in) */
+
+               toshiba_spi_write(0x28, 0, 0);  /* display off */
+               mdelay(1);
+               toshiba_spi_write(0xb8, 0x8002, 2);     /* output control */
+               mdelay(1);
+               toshiba_spi_write(0x10, 0x00, 1);       /* sleep mode in */
+               mdelay(85);             /* wait 85 msec */
+               toshiba_spi_write(0xb0, 0x00, 1);       /* deep standby in */
+               mdelay(1);
+               if (lcdc_toshiba_pdata->panel_config_gpio)
+                       lcdc_toshiba_pdata->panel_config_gpio(0);
+               toshiba_state.display_on = FALSE;
+               toshiba_state.disp_initialized = FALSE;
+       }
+       return 0;
+}
+
+static void lcdc_toshiba_set_backlight(struct msm_fb_data_type *mfd)
+{
+       int bl_level;
+       int ret = -EPERM;
+
+       bl_level = mfd->bl_level;
+       ret = pmic_set_led_intensity(LED_LCD, bl_level);
+
+       if (ret)
+               printk(KERN_WARNING "%s: can't set lcd backlight!\n",
+                               __func__);
+}
+
+static int __init toshiba_probe(struct platform_device *pdev)
+{
+       if (pdev->id == 0) {
+               lcdc_toshiba_pdata = pdev->dev.platform_data;
+               spi_pin_assign();
+               return 0;
+       }
+       msm_fb_add_device(pdev);
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = toshiba_probe,
+       .driver = {
+               .name   = "lcdc_toshiba_wvga",
+       },
+};
+
+static struct msm_fb_panel_data toshiba_panel_data = {
+       .on = lcdc_toshiba_panel_on,
+       .off = lcdc_toshiba_panel_off,
+       .set_backlight = lcdc_toshiba_set_backlight,
+};
+
+static struct platform_device this_device = {
+       .name   = "lcdc_toshiba_wvga",
+       .id     = 1,
+       .dev    = {
+               .platform_data = &toshiba_panel_data,
+       }
+};
+
+static int __init lcdc_toshiba_panel_init(void)
+{
+       int ret;
+       struct msm_panel_info *pinfo;
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+       if (mddi_get_client_id() != 0)
+               return 0;
+
+       ret = msm_fb_detect_client("lcdc_toshiba_wvga_pt");
+       if (ret)
+               return 0;
+
+#endif
+
+       ret = platform_driver_register(&this_driver);
+       if (ret)
+               return ret;
+
+       pinfo = &toshiba_panel_data.panel_info;
+       pinfo->xres = 480;
+       pinfo->yres = 800;
+       pinfo->type = LCDC_PANEL;
+       pinfo->pdest = DISPLAY_1;
+       pinfo->wait_cycle = 0;
+       pinfo->bpp = 18;
+       pinfo->fb_num = 2;
+       /* 30Mhz mdp_lcdc_pclk and mdp_lcdc_pad_pcl */
+       pinfo->clk_rate = 27648000;
+       pinfo->bl_max = 15;
+       pinfo->bl_min = 1;
+
+       pinfo->lcdc.h_back_porch = 184; /* hsw = 8 + hbp=184 */
+       pinfo->lcdc.h_front_porch = 4;
+       pinfo->lcdc.h_pulse_width = 8;
+       pinfo->lcdc.v_back_porch = 2;   /* vsw=1 + vbp = 2 */
+       pinfo->lcdc.v_front_porch = 3;
+       pinfo->lcdc.v_pulse_width = 1;
+       pinfo->lcdc.border_clr = 0;     /* blk */
+       pinfo->lcdc.underflow_clr = 0xff;       /* blue */
+       pinfo->lcdc.hsync_skew = 0;
+
+       ret = platform_device_register(&this_device);
+       if (ret)
+               platform_driver_unregister(&this_driver);
+
+       return ret;
+}
+
+device_initcall(lcdc_toshiba_panel_init);
diff --git a/drivers/staging/msm/lcdc_wxga.c b/drivers/staging/msm/lcdc_wxga.c
new file mode 100644 (file)
index 0000000..202c92c
--- /dev/null
@@ -0,0 +1,56 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int __init lcdc_wxga_init(void)
+{
+       int ret;
+       struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+       if (msm_fb_detect_client("lcdc_wxga"))
+               return 0;
+#endif
+
+       pinfo.xres = 1280;
+       pinfo.yres = 720;
+       pinfo.type = LCDC_PANEL;
+       pinfo.pdest = DISPLAY_1;
+       pinfo.wait_cycle = 0;
+       pinfo.bpp = 24;
+       pinfo.fb_num = 2;
+       pinfo.clk_rate = 74250000;
+
+       pinfo.lcdc.h_back_porch = 124;
+       pinfo.lcdc.h_front_porch = 110;
+       pinfo.lcdc.h_pulse_width = 136;
+       pinfo.lcdc.v_back_porch = 19;
+       pinfo.lcdc.v_front_porch = 5;
+       pinfo.lcdc.v_pulse_width = 6;
+       pinfo.lcdc.border_clr = 0;      /* blk */
+       pinfo.lcdc.underflow_clr = 0xff;        /* blue */
+       pinfo.lcdc.hsync_skew = 0;
+
+       ret = lcdc_device_register(&pinfo);
+       if (ret)
+               printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+       return ret;
+}
+
+module_init(lcdc_wxga_init);
diff --git a/drivers/staging/msm/logo.c b/drivers/staging/msm/logo.c
new file mode 100644 (file)
index 0000000..7272765
--- /dev/null
@@ -0,0 +1,98 @@
+/* drivers/video/msm/logo.c
+ *
+ * Show Logo in RLE 565 format
+ *
+ * Copyright (C) 2008 Google Incorporated
+ *
+ * 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/types.h>
+#include <linux/fb.h>
+#include <linux/vt_kern.h>
+#include <linux/unistd.h>
+#include <linux/syscalls.h>
+
+#include <linux/irq.h>
+#include <asm/system.h>
+
+#define fb_width(fb)   ((fb)->var.xres)
+#define fb_height(fb)  ((fb)->var.yres)
+#define fb_size(fb)    ((fb)->var.xres * (fb)->var.yres * 2)
+
+static void memset16(void *_ptr, unsigned short val, unsigned count)
+{
+       unsigned short *ptr = _ptr;
+       count >>= 1;
+       while (count--)
+               *ptr++ = val;
+}
+
+/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */
+int load_565rle_image(char *filename)
+{
+       struct fb_info *info;
+       int fd, err = 0;
+       unsigned count, max;
+       unsigned short *data, *bits, *ptr;
+
+       info = registered_fb[0];
+       if (!info) {
+               printk(KERN_WARNING "%s: Can not access framebuffer\n",
+                       __func__);
+               return -ENODEV;
+       }
+
+       fd = sys_open(filename, O_RDONLY, 0);
+       if (fd < 0) {
+               printk(KERN_WARNING "%s: Can not open %s\n",
+                       __func__, filename);
+               return -ENOENT;
+       }
+       count = (unsigned)sys_lseek(fd, (off_t)0, 2);
+       if (count == 0) {
+               sys_close(fd);
+               err = -EIO;
+               goto err_logo_close_file;
+       }
+       sys_lseek(fd, (off_t)0, 0);
+       data = kmalloc(count, GFP_KERNEL);
+       if (!data) {
+               printk(KERN_WARNING "%s: Can not alloc data\n", __func__);
+               err = -ENOMEM;
+               goto err_logo_close_file;
+       }
+       if ((unsigned)sys_read(fd, (char *)data, count) != count) {
+               err = -EIO;
+               goto err_logo_free_data;
+       }
+
+       max = fb_width(info) * fb_height(info);
+       ptr = data;
+       bits = (unsigned short *)(info->screen_base);
+       while (count > 3) {
+               unsigned n = ptr[0];
+               if (n > max)
+                       break;
+               memset16(bits, ptr[1], n << 1);
+               bits += n;
+               max -= n;
+               ptr += 2;
+               count -= 4;
+       }
+
+err_logo_free_data:
+       kfree(data);
+err_logo_close_file:
+       sys_close(fd);
+       return err;
+}
+EXPORT_SYMBOL(load_565rle_image);
diff --git a/drivers/staging/msm/mddi.c b/drivers/staging/msm/mddi.c
new file mode 100644 (file)
index 0000000..132eb1a
--- /dev/null
@@ -0,0 +1,375 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include "msm_fb.h"
+#include "mddihosti.h"
+#include "mddihost.h"
+#include <mach/gpio.h>
+#include <mach/clk.h>
+
+static int mddi_probe(struct platform_device *pdev);
+static int mddi_remove(struct platform_device *pdev);
+
+static int mddi_off(struct platform_device *pdev);
+static int mddi_on(struct platform_device *pdev);
+
+static int mddi_suspend(struct platform_device *pdev, pm_message_t state);
+static int mddi_resume(struct platform_device *pdev);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_early_suspend(struct early_suspend *h);
+static void mddi_early_resume(struct early_suspend *h);
+#endif
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static struct clk *mddi_clk;
+static struct clk *mddi_pclk;
+static struct mddi_platform_data *mddi_pdata;
+
+static struct platform_driver mddi_driver = {
+       .probe = mddi_probe,
+       .remove = mddi_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+#ifdef CONFIG_PM
+       .suspend = mddi_suspend,
+       .resume = mddi_resume,
+#endif
+#endif
+       .suspend_late = NULL,
+       .resume_early = NULL,
+       .shutdown = NULL,
+       .driver = {
+                  .name = "mddi",
+                  },
+};
+
+extern int int_mddi_pri_flag;
+
+static int mddi_off(struct platform_device *pdev)
+{
+       int ret = 0;
+
+       ret = panel_next_off(pdev);
+
+       if (mddi_pdata && mddi_pdata->mddi_power_save)
+               mddi_pdata->mddi_power_save(0);
+
+       return ret;
+}
+
+static int mddi_on(struct platform_device *pdev)
+{
+       int ret = 0;
+       u32 clk_rate;
+       struct msm_fb_data_type *mfd;
+
+       mfd = platform_get_drvdata(pdev);
+
+       if (mddi_pdata && mddi_pdata->mddi_power_save)
+               mddi_pdata->mddi_power_save(1);
+
+       clk_rate = mfd->fbi->var.pixclock;
+       clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+
+       if (mddi_pdata &&
+           mddi_pdata->mddi_sel_clk &&
+           mddi_pdata->mddi_sel_clk(&clk_rate))
+                       printk(KERN_ERR
+                         "%s: can't select mddi io clk targate rate = %d\n",
+                         __func__, clk_rate);
+
+       if (clk_set_min_rate(mddi_clk, clk_rate) < 0)
+               printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+                       __func__);
+
+       ret = panel_next_on(pdev);
+
+       return ret;
+}
+
+static int mddi_resource_initialized;
+
+static int mddi_probe(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+       struct platform_device *mdp_dev = NULL;
+       struct msm_fb_panel_data *pdata = NULL;
+       int rc;
+       resource_size_t size ;
+       u32 clk_rate;
+
+       if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
+               mddi_pdata = pdev->dev.platform_data;
+
+               size =  resource_size(&pdev->resource[0]);
+               msm_pmdh_base =  ioremap(pdev->resource[0].start, size);
+
+               MSM_FB_INFO("primary mddi base phy_addr = 0x%x virt = 0x%x\n",
+                               pdev->resource[0].start, (int) msm_pmdh_base);
+
+               if (unlikely(!msm_pmdh_base))
+                       return -ENOMEM;
+
+               if (mddi_pdata && mddi_pdata->mddi_power_save)
+                       mddi_pdata->mddi_power_save(1);
+
+               mddi_resource_initialized = 1;
+               return 0;
+       }
+
+       if (!mddi_resource_initialized)
+               return -EPERM;
+
+       mfd = platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+               return -ENOMEM;
+
+       mdp_dev = platform_device_alloc("mdp", pdev->id);
+       if (!mdp_dev)
+               return -ENOMEM;
+
+       /*
+        * link to the latest pdev
+        */
+       mfd->pdev = mdp_dev;
+       mfd->dest = DISPLAY_LCD;
+
+       /*
+        * alloc panel device data
+        */
+       if (platform_device_add_data
+           (mdp_dev, pdev->dev.platform_data,
+            sizeof(struct msm_fb_panel_data))) {
+               printk(KERN_ERR "mddi_probe: platform_device_add_data failed!\n");
+               platform_device_put(mdp_dev);
+               return -ENOMEM;
+       }
+       /*
+        * data chain
+        */
+       pdata = mdp_dev->dev.platform_data;
+       pdata->on = mddi_on;
+       pdata->off = mddi_off;
+       pdata->next = pdev;
+
+       /*
+        * get/set panel specific fb info
+        */
+       mfd->panel_info = pdata->panel_info;
+       mfd->fb_imgType = MDP_RGB_565;
+
+       clk_rate = mfd->panel_info.clk_max;
+       if (mddi_pdata &&
+           mddi_pdata->mddi_sel_clk &&
+           mddi_pdata->mddi_sel_clk(&clk_rate))
+                       printk(KERN_ERR
+                         "%s: can't select mddi io clk targate rate = %d\n",
+                         __func__, clk_rate);
+
+       if (clk_set_max_rate(mddi_clk, clk_rate) < 0)
+               printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
+       mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
+
+       /*
+        * set driver data
+        */
+       platform_set_drvdata(mdp_dev, mfd);
+
+       /*
+        * register in mdp driver
+        */
+       rc = platform_device_add(mdp_dev);
+       if (rc)
+               goto mddi_probe_err;
+
+       pdev_list[pdev_list_cnt++] = pdev;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       mfd->mddi_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+       mfd->mddi_early_suspend.suspend = mddi_early_suspend;
+       mfd->mddi_early_suspend.resume = mddi_early_resume;
+       register_early_suspend(&mfd->mddi_early_suspend);
+#endif
+
+       return 0;
+
+mddi_probe_err:
+       platform_device_put(mdp_dev);
+       return rc;
+}
+
+static int mddi_pad_ctrl;
+static int mddi_power_locked;
+static int mddi_is_in_suspend;
+
+void mddi_disable(int lock)
+{
+       mddi_host_type host_idx = MDDI_HOST_PRIM;
+
+       if (mddi_power_locked)
+               return;
+
+       if (lock)
+               mddi_power_locked = 1;
+
+       if (mddi_host_timer.function)
+               del_timer_sync(&mddi_host_timer);
+
+       mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL);
+       mddi_host_reg_out(PAD_CTL, 0x0);
+
+       if (clk_set_min_rate(mddi_clk, 0) < 0)
+               printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
+
+       clk_disable(mddi_clk);
+       if (mddi_pclk)
+               clk_disable(mddi_pclk);
+       disable_irq(INT_MDDI_PRI);
+
+       if (mddi_pdata && mddi_pdata->mddi_power_save)
+               mddi_pdata->mddi_power_save(0);
+}
+
+static int mddi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       if (mddi_is_in_suspend)
+               return 0;
+
+       mddi_is_in_suspend = 1;
+       mddi_disable(0);
+       return 0;
+}
+
+static int mddi_resume(struct platform_device *pdev)
+{
+       mddi_host_type host_idx = MDDI_HOST_PRIM;
+
+       if (!mddi_is_in_suspend)
+               return 0;
+
+       mddi_is_in_suspend = 0;
+
+       if (mddi_power_locked)
+               return 0;
+
+       enable_irq(INT_MDDI_PRI);
+       clk_enable(mddi_clk);
+       if (mddi_pclk)
+               clk_enable(mddi_pclk);
+       mddi_host_reg_out(PAD_CTL, mddi_pad_ctrl);
+
+       if (mddi_host_timer.function)
+               mddi_host_timer_service(0);
+
+       return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_early_suspend(struct early_suspend *h)
+{
+       pm_message_t state;
+       struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+                                                       mddi_early_suspend);
+
+       state.event = PM_EVENT_SUSPEND;
+       mddi_suspend(mfd->pdev, state);
+}
+
+static void mddi_early_resume(struct early_suspend *h)
+{
+       struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+                                                       mddi_early_suspend);
+       mddi_resume(mfd->pdev);
+}
+#endif
+
+static int mddi_remove(struct platform_device *pdev)
+{
+       if (mddi_host_timer.function)
+               del_timer_sync(&mddi_host_timer);
+
+       iounmap(msm_pmdh_base);
+
+       return 0;
+}
+
+static int mddi_register_driver(void)
+{
+       return platform_driver_register(&mddi_driver);
+}
+
+static int __init mddi_driver_init(void)
+{
+       int ret;
+
+       mddi_clk = clk_get(NULL, "mddi_clk");
+       if (IS_ERR(mddi_clk)) {
+               printk(KERN_ERR "can't find mddi_clk \n");
+               return PTR_ERR(mddi_clk);
+       }
+       clk_enable(mddi_clk);
+
+       mddi_pclk = clk_get(NULL, "mddi_pclk");
+       if (IS_ERR(mddi_pclk))
+               mddi_pclk = NULL;
+       else
+               clk_enable(mddi_pclk);
+
+       ret = mddi_register_driver();
+       if (ret) {
+               clk_disable(mddi_clk);
+               clk_put(mddi_clk);
+               if (mddi_pclk) {
+                       clk_disable(mddi_pclk);
+                       clk_put(mddi_pclk);
+               }
+               printk(KERN_ERR "mddi_register_driver() failed!\n");
+               return ret;
+       }
+
+       mddi_init();
+
+       return ret;
+}
+
+module_init(mddi_driver_init);
diff --git a/drivers/staging/msm/mddi_ext.c b/drivers/staging/msm/mddi_ext.c
new file mode 100644 (file)
index 0000000..c0c168c
--- /dev/null
@@ -0,0 +1,320 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <mach/clk.h>
+#include <linux/platform_device.h>
+
+#include "msm_fb.h"
+#include "mddihosti.h"
+
+static int mddi_ext_probe(struct platform_device *pdev);
+static int mddi_ext_remove(struct platform_device *pdev);
+
+static int mddi_ext_off(struct platform_device *pdev);
+static int mddi_ext_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state);
+static int mddi_ext_resume(struct platform_device *pdev);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_ext_early_suspend(struct early_suspend *h);
+static void mddi_ext_early_resume(struct early_suspend *h);
+#endif
+
+static struct platform_driver mddi_ext_driver = {
+       .probe = mddi_ext_probe,
+       .remove = mddi_ext_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+#ifdef CONFIG_PM
+       .suspend = mddi_ext_suspend,
+       .resume = mddi_ext_resume,
+#endif
+#endif
+       .resume_early = NULL,
+       .resume = NULL,
+       .shutdown = NULL,
+       .driver = {
+                  .name = "mddi_ext",
+                  },
+};
+
+static struct clk *mddi_ext_clk;
+static struct mddi_platform_data *mddi_ext_pdata;
+
+extern int int_mddi_ext_flag;
+
+static int mddi_ext_off(struct platform_device *pdev)
+{
+       int ret = 0;
+
+       ret = panel_next_off(pdev);
+       mddi_host_stop_ext_display();
+
+       return ret;
+}
+
+static int mddi_ext_on(struct platform_device *pdev)
+{
+       int ret = 0;
+       u32 clk_rate;
+       struct msm_fb_data_type *mfd;
+
+       mfd = platform_get_drvdata(pdev);
+
+       clk_rate = mfd->fbi->var.pixclock;
+       clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+
+       if (mddi_ext_pdata &&
+           mddi_ext_pdata->mddi_sel_clk &&
+           mddi_ext_pdata->mddi_sel_clk(&clk_rate))
+               printk(KERN_ERR
+                         "%s: can't select mddi io clk targate rate = %d\n",
+                         __func__, clk_rate);
+
+       if (clk_set_min_rate(mddi_ext_clk, clk_rate) < 0)
+               printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+                       __func__);
+
+       mddi_host_start_ext_display();
+       ret = panel_next_on(pdev);
+
+       return ret;
+}
+
+static int mddi_ext_resource_initialized;
+
+static int mddi_ext_probe(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+       struct platform_device *mdp_dev = NULL;
+       struct msm_fb_panel_data *pdata = NULL;
+       int rc;
+       resource_size_t size ;
+       u32 clk_rate;
+
+       if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
+               mddi_ext_pdata = pdev->dev.platform_data;
+
+               size =  resource_size(&pdev->resource[0]);
+               msm_emdh_base = ioremap(pdev->resource[0].start, size);
+
+               MSM_FB_INFO("external mddi base address = 0x%x\n",
+                               pdev->resource[0].start);
+
+               if (unlikely(!msm_emdh_base))
+                       return -ENOMEM;
+
+               mddi_ext_resource_initialized = 1;
+               return 0;
+       }
+
+       if (!mddi_ext_resource_initialized)
+               return -EPERM;
+
+       mfd = platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+               return -ENOMEM;
+
+       mdp_dev = platform_device_alloc("mdp", pdev->id);
+       if (!mdp_dev)
+               return -ENOMEM;
+
+       /*
+        * link to the latest pdev
+        */
+       mfd->pdev = mdp_dev;
+       mfd->dest = DISPLAY_EXT_MDDI;
+
+       /*
+        * alloc panel device data
+        */
+       if (platform_device_add_data
+           (mdp_dev, pdev->dev.platform_data,
+            sizeof(struct msm_fb_panel_data))) {
+               printk(KERN_ERR "mddi_ext_probe: platform_device_add_data failed!\n");
+               platform_device_put(mdp_dev);
+               return -ENOMEM;
+       }
+       /*
+        * data chain
+        */
+       pdata = mdp_dev->dev.platform_data;
+       pdata->on = mddi_ext_on;
+       pdata->off = mddi_ext_off;
+       pdata->next = pdev;
+
+       /*
+        * get/set panel specific fb info
+        */
+       mfd->panel_info = pdata->panel_info;
+       mfd->fb_imgType = MDP_RGB_565;
+
+       clk_rate = mfd->panel_info.clk_max;
+       if (mddi_ext_pdata &&
+           mddi_ext_pdata->mddi_sel_clk &&
+           mddi_ext_pdata->mddi_sel_clk(&clk_rate))
+                       printk(KERN_ERR
+                         "%s: can't select mddi io clk targate rate = %d\n",
+                         __func__, clk_rate);
+
+       if (clk_set_max_rate(mddi_ext_clk, clk_rate) < 0)
+               printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
+       mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
+
+       /*
+        * set driver data
+        */
+       platform_set_drvdata(mdp_dev, mfd);
+
+       /*
+        * register in mdp driver
+        */
+       rc = platform_device_add(mdp_dev);
+       if (rc)
+               goto mddi_ext_probe_err;
+
+       pdev_list[pdev_list_cnt++] = pdev;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       mfd->mddi_ext_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+       mfd->mddi_ext_early_suspend.suspend = mddi_ext_early_suspend;
+       mfd->mddi_ext_early_suspend.resume = mddi_ext_early_resume;
+       register_early_suspend(&mfd->mddi_ext_early_suspend);
+#endif
+
+       return 0;
+
+mddi_ext_probe_err:
+       platform_device_put(mdp_dev);
+       return rc;
+}
+
+static int mddi_ext_is_in_suspend;
+
+static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       if (mddi_ext_is_in_suspend)
+               return 0;
+
+       mddi_ext_is_in_suspend = 1;
+
+       if (clk_set_min_rate(mddi_ext_clk, 0) < 0)
+               printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
+
+       clk_disable(mddi_ext_clk);
+       disable_irq(INT_MDDI_EXT);
+
+       return 0;
+}
+
+static int mddi_ext_resume(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+
+       mfd = platform_get_drvdata(pdev);
+
+       if (!mddi_ext_is_in_suspend)
+               return 0;
+
+       mddi_ext_is_in_suspend = 0;
+       enable_irq(INT_MDDI_EXT);
+
+       clk_enable(mddi_ext_clk);
+
+       return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_ext_early_suspend(struct early_suspend *h)
+{
+       pm_message_t state;
+       struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+                                                       mddi_ext_early_suspend);
+
+       state.event = PM_EVENT_SUSPEND;
+       mddi_ext_suspend(mfd->pdev, state);
+}
+
+static void mddi_ext_early_resume(struct early_suspend *h)
+{
+       struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+                                                       mddi_ext_early_suspend);
+       mddi_ext_resume(mfd->pdev);
+}
+#endif
+
+static int mddi_ext_remove(struct platform_device *pdev)
+{
+       iounmap(msm_emdh_base);
+       return 0;
+}
+
+static int mddi_ext_register_driver(void)
+{
+       return platform_driver_register(&mddi_ext_driver);
+}
+
+static int __init mddi_ext_driver_init(void)
+{
+       int ret;
+
+       mddi_ext_clk = clk_get(NULL, "emdh_clk");
+       if (IS_ERR(mddi_ext_clk)) {
+               printk(KERN_ERR "can't find emdh_clk\n");
+               return PTR_ERR(mddi_ext_clk);
+       }
+       clk_enable(mddi_ext_clk);
+
+       ret = mddi_ext_register_driver();
+       if (ret) {
+               clk_disable(mddi_ext_clk);
+               clk_put(mddi_ext_clk);
+               printk(KERN_ERR "mddi_ext_register_driver() failed!\n");
+               return ret;
+       }
+       mddi_init();
+
+       return ret;
+}
+
+module_init(mddi_ext_driver_init);
diff --git a/drivers/staging/msm/mddi_ext_lcd.c b/drivers/staging/msm/mddi_ext_lcd.c
new file mode 100644 (file)
index 0000000..502e80d
--- /dev/null
@@ -0,0 +1,91 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+static int mddi_ext_lcd_on(struct platform_device *pdev);
+static int mddi_ext_lcd_off(struct platform_device *pdev);
+
+static int mddi_ext_lcd_on(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static int mddi_ext_lcd_off(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static int __init mddi_ext_lcd_probe(struct platform_device *pdev)
+{
+       msm_fb_add_device(pdev);
+
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = mddi_ext_lcd_probe,
+       .driver = {
+               .name   = "extmddi_svga",
+       },
+};
+
+static struct msm_fb_panel_data mddi_ext_lcd_panel_data = {
+       .panel_info.xres = 800,
+       .panel_info.yres = 600,
+       .panel_info.type = EXT_MDDI_PANEL,
+       .panel_info.pdest = DISPLAY_1,
+       .panel_info.wait_cycle = 0,
+       .panel_info.bpp = 18,
+       .panel_info.fb_num = 2,
+       .panel_info.clk_rate = 122880000,
+       .panel_info.clk_min  = 120000000,
+       .panel_info.clk_max  = 125000000,
+       .on = mddi_ext_lcd_on,
+       .off = mddi_ext_lcd_off,
+};
+
+static struct platform_device this_device = {
+       .name   = "extmddi_svga",
+       .id     = 0,
+       .dev    = {
+               .platform_data = &mddi_ext_lcd_panel_data,
+       }
+};
+
+static int __init mddi_ext_lcd_init(void)
+{
+       int ret;
+       struct msm_panel_info *pinfo;
+
+       ret = platform_driver_register(&this_driver);
+       if (!ret) {
+               pinfo = &mddi_ext_lcd_panel_data.panel_info;
+               pinfo->lcd.vsync_enable = FALSE;
+               pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+
+               ret = platform_device_register(&this_device);
+               if (ret)
+                       platform_driver_unregister(&this_driver);
+       }
+
+       return ret;
+}
+
+module_init(mddi_ext_lcd_init);
diff --git a/drivers/staging/msm/mddi_prism.c b/drivers/staging/msm/mddi_prism.c
new file mode 100644 (file)
index 0000000..489d404
--- /dev/null
@@ -0,0 +1,114 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+static int prism_lcd_on(struct platform_device *pdev);
+static int prism_lcd_off(struct platform_device *pdev);
+
+static int prism_lcd_on(struct platform_device *pdev)
+{
+       /* Set the MDP pixel data attributes for Primary Display */
+       mddi_host_write_pix_attr_reg(0x00C3);
+
+       return 0;
+}
+
+static int prism_lcd_off(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static int __init prism_probe(struct platform_device *pdev)
+{
+       msm_fb_add_device(pdev);
+
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = prism_probe,
+       .driver = {
+               .name   = "mddi_prism_wvga",
+       },
+};
+
+static struct msm_fb_panel_data prism_panel_data = {
+       .on = prism_lcd_on,
+       .off = prism_lcd_off,
+};
+
+static struct platform_device this_device = {
+       .name   = "mddi_prism_wvga",
+       .id     = 0,
+       .dev    = {
+               .platform_data = &prism_panel_data,
+       }
+};
+
+static int __init prism_init(void)
+{
+       int ret;
+       struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+       u32 id;
+
+       ret = msm_fb_detect_client("mddi_prism_wvga");
+       if (ret == -ENODEV)
+               return 0;
+
+       if (ret) {
+               id = mddi_get_client_id();
+
+               if (((id >> 16) != 0x4474) || ((id & 0xffff) == 0x8960))
+                       return 0;
+       }
+#endif
+       ret = platform_driver_register(&this_driver);
+       if (!ret) {
+               pinfo = &prism_panel_data.panel_info;
+               pinfo->xres = 800;
+               pinfo->yres = 480;
+               pinfo->type = MDDI_PANEL;
+               pinfo->pdest = DISPLAY_1;
+               pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+               pinfo->wait_cycle = 0;
+               pinfo->bpp = 18;
+               pinfo->fb_num = 2;
+               pinfo->clk_rate = 153600000;
+               pinfo->clk_min = 150000000;
+               pinfo->clk_max = 160000000;
+               pinfo->lcd.vsync_enable = TRUE;
+               pinfo->lcd.refx100 = 6050;
+               pinfo->lcd.v_back_porch = 23;
+               pinfo->lcd.v_front_porch = 20;
+               pinfo->lcd.v_pulse_width = 105;
+               pinfo->lcd.hw_vsync_mode = TRUE;
+               pinfo->lcd.vsync_notifier_period = 0;
+
+               ret = platform_device_register(&this_device);
+               if (ret)
+                       platform_driver_unregister(&this_driver);
+       }
+
+       return ret;
+}
+
+module_init(prism_init);
diff --git a/drivers/staging/msm/mddi_sharp.c b/drivers/staging/msm/mddi_sharp.c
new file mode 100644 (file)
index 0000000..1da1be4
--- /dev/null
@@ -0,0 +1,892 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#define SHARP_QVGA_PRIM 1
+#define SHARP_128X128_SECD 2
+
+extern uint32 mddi_host_core_version;
+static boolean mddi_debug_prim_wait = FALSE;
+static boolean mddi_sharp_vsync_wake = TRUE;
+static boolean mddi_sharp_monitor_refresh_value = TRUE;
+static boolean mddi_sharp_report_refresh_measurements = FALSE;
+static uint32 mddi_sharp_rows_per_second = 13830;      /* 5200000/376 */
+static uint32 mddi_sharp_rows_per_refresh = 338;
+static uint32 mddi_sharp_usecs_per_refresh = 24440;    /* (376+338)/5200000 */
+static boolean mddi_sharp_debug_60hz_refresh = FALSE;
+
+extern mddi_gpio_info_type mddi_gpio;
+extern boolean mddi_vsync_detect_enabled;
+static msm_fb_vsync_handler_type mddi_sharp_vsync_handler;
+static void *mddi_sharp_vsync_handler_arg;
+static uint16 mddi_sharp_vsync_attempts;
+
+static void mddi_sharp_prim_lcd_init(void);
+static void mddi_sharp_sub_lcd_init(void);
+static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd);
+static void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler,
+                                        void *);
+static void mddi_sharp_lcd_vsync_detected(boolean detected);
+static struct msm_panel_common_pdata *mddi_sharp_pdata;
+
+#define REG_SYSCTL    0x0000
+#define REG_INTR    0x0006
+#define REG_CLKCNF    0x000C
+#define REG_CLKDIV1    0x000E
+#define REG_CLKDIV2    0x0010
+
+#define REG_GIOD    0x0040
+#define REG_GIOA    0x0042
+
+#define REG_AGM      0x010A
+#define REG_FLFT    0x0110
+#define REG_FRGT    0x0112
+#define REG_FTOP    0x0114
+#define REG_FBTM    0x0116
+#define REG_FSTRX    0x0118
+#define REG_FSTRY    0x011A
+#define REG_VRAM    0x0202
+#define REG_SSDCTL    0x0330
+#define REG_SSD0    0x0332
+#define REG_PSTCTL1    0x0400
+#define REG_PSTCTL2    0x0402
+#define REG_PTGCTL    0x042A
+#define REG_PTHP    0x042C
+#define REG_PTHB    0x042E
+#define REG_PTHW    0x0430
+#define REG_PTHF    0x0432
+#define REG_PTVP    0x0434
+#define REG_PTVB    0x0436
+#define REG_PTVW    0x0438
+#define REG_PTVF    0x043A
+#define REG_VBLKS    0x0458
+#define REG_VBLKE    0x045A
+#define REG_SUBCTL    0x0700
+#define REG_SUBTCMD    0x0702
+#define REG_SUBTCMDD  0x0704
+#define REG_REVBYTE    0x0A02
+#define REG_REVCNT    0x0A04
+#define REG_REVATTR    0x0A06
+#define REG_REVFMT    0x0A08
+
+#define SHARP_SUB_UNKNOWN 0xffffffff
+#define SHARP_SUB_HYNIX 1
+#define SHARP_SUB_ROHM  2
+
+static uint32 sharp_subpanel_type = SHARP_SUB_UNKNOWN;
+
+static void sub_through_write(int sub_rs, uint32 sub_data)
+{
+       mddi_queue_register_write(REG_SUBTCMDD, sub_data, FALSE, 0);
+
+       /* CS=1,RD=1,WE=1,RS=sub_rs */
+       mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
+
+       /* CS=0,RD=1,WE=1,RS=sub_rs */
+       mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+       /* CS=0,RD=1,WE=0,RS=sub_rs */
+       mddi_queue_register_write(REG_SUBTCMD, 0x0004 | sub_rs, FALSE, 0);
+
+       /* CS=0,RD=1,WE=1,RS=sub_rs */
+       mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+       /* CS=1,RD=1,WE=1,RS=sub_rs */
+       mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
+}
+
+static uint32 sub_through_read(int sub_rs)
+{
+       uint32 sub_data;
+
+       /* CS=1,RD=1,WE=1,RS=sub_rs */
+       mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
+
+       /* CS=0,RD=1,WE=1,RS=sub_rs */
+       mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+       /* CS=0,RD=1,WE=0,RS=sub_rs */
+       mddi_queue_register_write(REG_SUBTCMD, 0x0002 | sub_rs, TRUE, 0);
+
+       mddi_queue_register_read(REG_SUBTCMDD, &sub_data, TRUE, 0);
+
+       /* CS=0,RD=1,WE=1,RS=sub_rs */
+       mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+       /* CS=1,RD=1,WE=1,RS=sub_rs */
+       mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
+
+       return sub_data;
+}
+
+static void serigo(uint32 ssd)
+{
+       uint32 ssdctl;
+
+       mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
+       ssdctl = ((ssdctl & 0xE7) | 0x02);
+
+       mddi_queue_register_write(REG_SSD0, ssd, FALSE, 0);
+       mddi_queue_register_write(REG_SSDCTL, ssdctl, TRUE, 0);
+
+       do {
+               mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
+       } while ((ssdctl & 0x0002) != 0);
+
+       if (mddi_debug_prim_wait)
+               mddi_wait(2);
+}
+
+static void mddi_sharp_lcd_powerdown(void)
+{
+       serigo(0x0131);
+       serigo(0x0300);
+       mddi_wait(40);
+       serigo(0x0135);
+       mddi_wait(20);
+       serigo(0x2122);
+       mddi_wait(20);
+       serigo(0x0201);
+       mddi_wait(20);
+       serigo(0x2100);
+       mddi_wait(20);
+       serigo(0x2000);
+       mddi_wait(20);
+
+       mddi_queue_register_write(REG_PSTCTL1, 0x1, TRUE, 0);
+       mddi_wait(100);
+       mddi_queue_register_write(REG_PSTCTL1, 0x0, TRUE, 0);
+       mddi_wait(2);
+       mddi_queue_register_write(REG_SYSCTL, 0x1, TRUE, 0);
+       mddi_wait(2);
+       mddi_queue_register_write(REG_CLKDIV1, 0x3, TRUE, 0);
+       mddi_wait(2);
+       mddi_queue_register_write(REG_SSDCTL, 0x0000, TRUE, 0); /* SSDRESET */
+       mddi_queue_register_write(REG_SYSCTL, 0x0, TRUE, 0);
+       mddi_wait(2);
+}
+
+static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd)
+{
+       uint32 regdata;
+       int32 level;
+       int max = mfd->panel_info.bl_max;
+       int min = mfd->panel_info.bl_min;
+
+       if (mddi_sharp_pdata && mddi_sharp_pdata->backlight_level) {
+               level = mddi_sharp_pdata->backlight_level(mfd->bl_level,
+                                                         max,
+                                                         min);
+
+               if (level < 0)
+                       return;
+
+               /* use Rodem GPIO(2:0) to give 8 levels of backlight (7-0) */
+               /* Set lower 3 GPIOs as Outputs (set to 0) */
+               mddi_queue_register_read(REG_GIOA, &regdata, TRUE, 0);
+               mddi_queue_register_write(REG_GIOA, regdata & 0xfff8, TRUE, 0);
+
+               /* Set lower 3 GPIOs as level */
+               mddi_queue_register_read(REG_GIOD, &regdata, TRUE, 0);
+               mddi_queue_register_write(REG_GIOD,
+                         (regdata & 0xfff8) | (0x07 & level), TRUE, 0);
+       }
+}
+
+static void mddi_sharp_prim_lcd_init(void)
+{
+       mddi_queue_register_write(REG_SYSCTL, 0x4000, TRUE, 0);
+       mddi_wait(1);
+       mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
+       mddi_wait(5);
+       mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
+       mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
+
+       /* new reg write below */
+       if (mddi_sharp_debug_60hz_refresh)
+               mddi_queue_register_write(REG_CLKCNF, 0x070d, FALSE, 0);
+       else
+               mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
+
+       mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
+       mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
+       mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
+       mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
+       mddi_queue_register_write(REG_PTHW, 240, FALSE, 0);
+       if (mddi_sharp_debug_60hz_refresh)
+               mddi_queue_register_write(REG_PTHF, 12, FALSE, 0);
+       else
+               mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
+
+       mddi_wait(1);
+
+       mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
+       mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
+       mddi_queue_register_write(REG_PTVW, 320, FALSE, 0);
+       mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
+
+       mddi_wait(1);
+
+       /* vram_color set REG_AGM???? */
+       mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
+
+       mddi_queue_register_write(REG_SSDCTL, 0x0000, FALSE, 0);
+       mddi_queue_register_write(REG_SSDCTL, 0x0001, TRUE, 0);
+       mddi_wait(1);
+       mddi_queue_register_write(REG_PSTCTL1, 0x0001, TRUE, 0);
+       mddi_wait(10);
+
+       serigo(0x0701);
+       /* software reset */
+       mddi_wait(1);
+       /* Wait over 50us */
+
+       serigo(0x0400);
+       /* DCLK~ACHSYNC~ACVSYNC polarity setting */
+       serigo(0x2900);
+       /* EEPROM start read address setting */
+       serigo(0x2606);
+       /* EEPROM start read register setting */
+       mddi_wait(20);
+       /* Wait over 20ms */
+
+       serigo(0x0503);
+       /* Horizontal timing setting */
+       serigo(0x062C);
+       /* Veritical timing setting */
+       serigo(0x2001);
+       /* power initialize setting(VDC2) */
+       mddi_wait(20);
+       /* Wait over 20ms */
+
+       serigo(0x2120);
+       /* Initialize power setting(CPS) */
+       mddi_wait(20);
+       /* Wait over 20ms */
+
+       serigo(0x2130);
+       /* Initialize power setting(CPS) */
+       mddi_wait(20);
+       /* Wait over 20ms */
+
+       serigo(0x2132);
+       /* Initialize power setting(CPS) */
+       mddi_wait(10);
+       /* Wait over 10ms */
+
+       serigo(0x2133);
+       /* Initialize power setting(CPS) */
+       mddi_wait(20);
+       /* Wait over 20ms */
+
+       serigo(0x0200);
+       /* Panel initialize release(INIT) */
+       mddi_wait(1);
+       /* Wait over 1ms */
+
+       serigo(0x0131);
+       /* Panel setting(CPS) */
+       mddi_wait(1);
+       /* Wait over 1ms */
+
+       mddi_queue_register_write(REG_PSTCTL1, 0x0003, TRUE, 0);
+
+       /* if (FFA LCD is upside down) -> serigo(0x0100); */
+       serigo(0x0130);
+
+       /* Black mask release(display ON) */
+       mddi_wait(1);
+       /* Wait over 1ms */
+
+       if (mddi_sharp_vsync_wake) {
+               mddi_queue_register_write(REG_VBLKS, 0x1001, TRUE, 0);
+               mddi_queue_register_write(REG_VBLKE, 0x1002, TRUE, 0);
+       }
+
+       /* Set the MDP pixel data attributes for Primary Display */
+       mddi_host_write_pix_attr_reg(0x00C3);
+       return;
+
+}
+
+void mddi_sharp_sub_lcd_init(void)
+{
+
+       mddi_queue_register_write(REG_SYSCTL, 0x4000, FALSE, 0);
+       mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
+       mddi_wait(100);
+
+       mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
+       mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
+       mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
+       mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
+       mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
+       mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
+       mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
+       mddi_queue_register_write(REG_PTHW, 128, FALSE, 0);
+       mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
+       mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
+       mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
+       mddi_queue_register_write(REG_PTVW, 128, FALSE, 0);
+       mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
+
+       /* Now the sub display..... */
+       /* Reset High */
+       mddi_queue_register_write(REG_SUBCTL, 0x0200, FALSE, 0);
+       /* CS=1,RD=1,WE=1,RS=1 */
+       mddi_queue_register_write(REG_SUBTCMD, 0x000f, TRUE, 0);
+       mddi_wait(1);
+       /* Wait 5us */
+
+       if (sharp_subpanel_type == SHARP_SUB_UNKNOWN) {
+               uint32 data;
+
+               sub_through_write(1, 0x05);
+               sub_through_write(1, 0x6A);
+               sub_through_write(1, 0x1D);
+               sub_through_write(1, 0x05);
+               data = sub_through_read(1);
+               if (data == 0x6A) {
+                       sharp_subpanel_type = SHARP_SUB_HYNIX;
+               } else {
+                       sub_through_write(0, 0x36);
+                       sub_through_write(1, 0xA8);
+                       sub_through_write(0, 0x09);
+                       data = sub_through_read(1);
+                       data = sub_through_read(1);
+                       if (data == 0x54) {
+                               sub_through_write(0, 0x36);
+                               sub_through_write(1, 0x00);
+                               sharp_subpanel_type = SHARP_SUB_ROHM;
+                       }
+               }
+       }
+
+       if (sharp_subpanel_type == SHARP_SUB_HYNIX) {
+               sub_through_write(1, 0x00);     /* Display setting 1 */
+               sub_through_write(1, 0x04);
+               sub_through_write(1, 0x01);
+               sub_through_write(1, 0x05);
+               sub_through_write(1, 0x0280);
+               sub_through_write(1, 0x0301);
+               sub_through_write(1, 0x0402);
+               sub_through_write(1, 0x0500);
+               sub_through_write(1, 0x0681);
+               sub_through_write(1, 0x077F);
+               sub_through_write(1, 0x08C0);
+               sub_through_write(1, 0x0905);
+               sub_through_write(1, 0x0A02);
+               sub_through_write(1, 0x0B00);
+               sub_through_write(1, 0x0C00);
+               sub_through_write(1, 0x0D00);
+               sub_through_write(1, 0x0E00);
+               sub_through_write(1, 0x0F00);
+
+               sub_through_write(1, 0x100B);   /* Display setting 2 */
+               sub_through_write(1, 0x1103);
+               sub_through_write(1, 0x1237);
+               sub_through_write(1, 0x1300);
+               sub_through_write(1, 0x1400);
+               sub_through_write(1, 0x1500);
+               sub_through_write(1, 0x1605);
+               sub_through_write(1, 0x1700);
+               sub_through_write(1, 0x1800);
+               sub_through_write(1, 0x192E);
+               sub_through_write(1, 0x1A00);
+               sub_through_write(1, 0x1B00);
+               sub_through_write(1, 0x1C00);
+
+               sub_through_write(1, 0x151A);   /* Power setting */
+
+               sub_through_write(1, 0x2002);   /* Gradation Palette setting */
+               sub_through_write(1, 0x2107);
+               sub_through_write(1, 0x220C);
+               sub_through_write(1, 0x2310);
+               sub_through_write(1, 0x2414);
+               sub_through_write(1, 0x2518);
+               sub_through_write(1, 0x261C);
+               sub_through_write(1, 0x2720);
+               sub_through_write(1, 0x2824);
+               sub_through_write(1, 0x2928);
+               sub_through_write(1, 0x2A2B);
+               sub_through_write(1, 0x2B2E);
+               sub_through_write(1, 0x2C31);
+               sub_through_write(1, 0x2D34);
+               sub_through_write(1, 0x2E37);
+               sub_through_write(1, 0x2F3A);
+               sub_through_write(1, 0x303C);
+               sub_through_write(1, 0x313E);
+               sub_through_write(1, 0x323F);
+               sub_through_write(1, 0x3340);
+               sub_through_write(1, 0x3441);
+               sub_through_write(1, 0x3543);
+               sub_through_write(1, 0x3646);
+               sub_through_write(1, 0x3749);
+               sub_through_write(1, 0x384C);
+               sub_through_write(1, 0x394F);
+               sub_through_write(1, 0x3A52);
+               sub_through_write(1, 0x3B59);
+               sub_through_write(1, 0x3C60);
+               sub_through_write(1, 0x3D67);
+               sub_through_write(1, 0x3E6E);
+               sub_through_write(1, 0x3F7F);
+               sub_through_write(1, 0x4001);
+               sub_through_write(1, 0x4107);
+               sub_through_write(1, 0x420C);
+               sub_through_write(1, 0x4310);
+               sub_through_write(1, 0x4414);
+               sub_through_write(1, 0x4518);
+               sub_through_write(1, 0x461C);
+               sub_through_write(1, 0x4720);
+               sub_through_write(1, 0x4824);
+               sub_through_write(1, 0x4928);
+               sub_through_write(1, 0x4A2B);
+               sub_through_write(1, 0x4B2E);
+               sub_through_write(1, 0x4C31);
+               sub_through_write(1, 0x4D34);
+               sub_through_write(1, 0x4E37);
+               sub_through_write(1, 0x4F3A);
+               sub_through_write(1, 0x503C);
+               sub_through_write(1, 0x513E);
+               sub_through_write(1, 0x523F);
+               sub_through_write(1, 0x5340);
+               sub_through_write(1, 0x5441);
+               sub_through_write(1, 0x5543);
+               sub_through_write(1, 0x5646);
+               sub_through_write(1, 0x5749);
+               sub_through_write(1, 0x584C);
+               sub_through_write(1, 0x594F);
+               sub_through_write(1, 0x5A52);
+               sub_through_write(1, 0x5B59);
+               sub_through_write(1, 0x5C60);
+               sub_through_write(1, 0x5D67);
+               sub_through_write(1, 0x5E6E);
+               sub_through_write(1, 0x5F7E);
+               sub_through_write(1, 0x6000);
+               sub_through_write(1, 0x6107);
+               sub_through_write(1, 0x620C);
+               sub_through_write(1, 0x6310);
+               sub_through_write(1, 0x6414);
+               sub_through_write(1, 0x6518);
+               sub_through_write(1, 0x661C);
+               sub_through_write(1, 0x6720);
+               sub_through_write(1, 0x6824);
+               sub_through_write(1, 0x6928);
+               sub_through_write(1, 0x6A2B);
+               sub_through_write(1, 0x6B2E);
+               sub_through_write(1, 0x6C31);
+               sub_through_write(1, 0x6D34);
+               sub_through_write(1, 0x6E37);
+               sub_through_write(1, 0x6F3A);
+               sub_through_write(1, 0x703C);
+               sub_through_write(1, 0x713E);
+               sub_through_write(1, 0x723F);
+               sub_through_write(1, 0x7340);
+               sub_through_write(1, 0x7441);
+               sub_through_write(1, 0x7543);
+               sub_through_write(1, 0x7646);
+               sub_through_write(1, 0x7749);
+               sub_through_write(1, 0x784C);
+               sub_through_write(1, 0x794F);
+               sub_through_write(1, 0x7A52);
+               sub_through_write(1, 0x7B59);
+               sub_through_write(1, 0x7C60);
+               sub_through_write(1, 0x7D67);
+               sub_through_write(1, 0x7E6E);
+               sub_through_write(1, 0x7F7D);
+
+               sub_through_write(1, 0x1851);   /* Display on */
+
+               mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
+
+               /* 1 pixel / 1 post clock */
+               mddi_queue_register_write(REG_CLKDIV2, 0x3b00, FALSE, 0);
+
+               /* SUB LCD select */
+               mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
+
+               /* RS=0,command initiate number=0,select master mode */
+               mddi_queue_register_write(REG_SUBCTL, 0x0202, FALSE, 0);
+
+               /* Sub LCD Data transform start */
+               mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
+
+       } else if (sharp_subpanel_type == SHARP_SUB_ROHM) {
+
+               sub_through_write(0, 0x01);     /* Display setting */
+               sub_through_write(1, 0x00);
+
+               mddi_wait(1);
+               /* Wait 100us  <----- ******* Update 2005/01/24 */
+
+               sub_through_write(0, 0xB6);
+               sub_through_write(1, 0x0C);
+               sub_through_write(1, 0x4A);
+               sub_through_write(1, 0x20);
+               sub_through_write(0, 0x3A);
+               sub_through_write(1, 0x05);
+               sub_through_write(0, 0xB7);
+               sub_through_write(1, 0x01);
+               sub_through_write(0, 0xBA);
+               sub_through_write(1, 0x20);
+               sub_through_write(1, 0x02);
+               sub_through_write(0, 0x25);
+               sub_through_write(1, 0x4F);
+               sub_through_write(0, 0xBB);
+               sub_through_write(1, 0x00);
+               sub_through_write(0, 0x36);
+               sub_through_write(1, 0x00);
+               sub_through_write(0, 0xB1);
+               sub_through_write(1, 0x05);
+               sub_through_write(0, 0xBE);
+               sub_through_write(1, 0x80);
+               sub_through_write(0, 0x26);
+               sub_through_write(1, 0x01);
+               sub_through_write(0, 0x2A);
+               sub_through_write(1, 0x02);
+               sub_through_write(1, 0x81);
+               sub_through_write(0, 0x2B);
+               sub_through_write(1, 0x00);
+               sub_through_write(1, 0x7F);
+
+               sub_through_write(0, 0x2C);
+               sub_through_write(0, 0x11);     /* Sleep mode off */
+
+               mddi_wait(1);
+               /* Wait 100 ms <----- ******* Update 2005/01/24 */
+
+               sub_through_write(0, 0x29);     /* Display on */
+               sub_through_write(0, 0xB3);
+               sub_through_write(1, 0x20);
+               sub_through_write(1, 0xAA);
+               sub_through_write(1, 0xA0);
+               sub_through_write(1, 0x20);
+               sub_through_write(1, 0x30);
+               sub_through_write(1, 0xA6);
+               sub_through_write(1, 0xFF);
+               sub_through_write(1, 0x9A);
+               sub_through_write(1, 0x9F);
+               sub_through_write(1, 0xAF);
+               sub_through_write(1, 0xBC);
+               sub_through_write(1, 0xCF);
+               sub_through_write(1, 0xDF);
+               sub_through_write(1, 0x20);
+               sub_through_write(1, 0x9C);
+               sub_through_write(1, 0x8A);
+
+               sub_through_write(0, 0x002C);   /* Display on */
+
+               /* 1 pixel / 2 post clock */
+               mddi_queue_register_write(REG_CLKDIV2, 0x7b00, FALSE, 0);
+
+               /* SUB LCD select */
+               mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
+
+               /* RS=1,command initiate number=0,select master mode */
+               mddi_queue_register_write(REG_SUBCTL, 0x0242, FALSE, 0);
+
+               /* Sub LCD Data transform start */
+               mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
+
+       }
+
+       /* Set the MDP pixel data attributes for Sub Display */
+       mddi_host_write_pix_attr_reg(0x00C0);
+}
+
+void mddi_sharp_lcd_vsync_detected(boolean detected)
+{
+       /* static timetick_type start_time = 0; */
+       static struct timeval start_time;
+       static boolean first_time = TRUE;
+       /* uint32 mdp_cnt_val = 0; */
+       /* timetick_type elapsed_us; */
+       struct timeval now;
+       uint32 elapsed_us;
+       uint32 num_vsyncs;
+
+       if ((detected) || (mddi_sharp_vsync_attempts > 5)) {
+               if ((detected) && (mddi_sharp_monitor_refresh_value)) {
+                       /* if (start_time != 0) */
+                       if (!first_time) {
+                               jiffies_to_timeval(jiffies, &now);
+                               elapsed_us =
+                                   (now.tv_sec - start_time.tv_sec) * 1000000 +
+                                   now.tv_usec - start_time.tv_usec;
+                               /*
+                               * LCD is configured for a refresh every usecs,
+                               * so to determine the number of vsyncs that
+                               * have occurred since the last measurement add
+                               * half that to the time difference and divide
+                               * by the refresh rate.
+                               */
+                               num_vsyncs = (elapsed_us +
+                                             (mddi_sharp_usecs_per_refresh >>
+                                              1)) /
+                                   mddi_sharp_usecs_per_refresh;
+                               /*
+                                * LCD is configured for * hsyncs (rows) per
+                                * refresh cycle. Calculate new rows_per_second
+                                * value based upon these new measurements.
+                                * MDP can update with this new value.
+                                */
+                               mddi_sharp_rows_per_second =
+                                   (mddi_sharp_rows_per_refresh * 1000 *
+                                    num_vsyncs) / (elapsed_us / 1000);
+                       }
+                       /* start_time = timetick_get(); */
+                       first_time = FALSE;
+                       jiffies_to_timeval(jiffies, &start_time);
+                       if (mddi_sharp_report_refresh_measurements) {
+                               /* mdp_cnt_val = MDP_LINE_COUNT; */
+                       }
+               }
+               /* if detected = TRUE, client initiated wakeup was detected */
+               if (mddi_sharp_vsync_handler != NULL) {
+                       (*mddi_sharp_vsync_handler)
+                           (mddi_sharp_vsync_handler_arg);
+                       mddi_sharp_vsync_handler = NULL;
+               }
+               mddi_vsync_detect_enabled = FALSE;
+               mddi_sharp_vsync_attempts = 0;
+               /* need to clear this vsync wakeup */
+               if (!mddi_queue_register_write_int(REG_INTR, 0x0000)) {
+                       MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
+               }
+               if (!detected) {
+                       /* give up after 5 failed attempts but show error */
+                       MDDI_MSG_NOTICE("Vsync detection failed!\n");
+               } else if ((mddi_sharp_monitor_refresh_value) &&
+                       (mddi_sharp_report_refresh_measurements)) {
+                       MDDI_MSG_NOTICE("  Lines Per Second=%d!\n",
+                               mddi_sharp_rows_per_second);
+               }
+       } else
+               /* if detected = FALSE, we woke up from hibernation, but did not
+                * detect client initiated wakeup.
+                */
+               mddi_sharp_vsync_attempts++;
+}
+
+/* ISR to be executed */
+void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg)
+{
+       boolean error = FALSE;
+       unsigned long flags;
+
+       /* Disable interrupts */
+       spin_lock_irqsave(&mddi_host_spin_lock, flags);
+       /* INTLOCK(); */
+
+       if (mddi_sharp_vsync_handler != NULL)
+               error = TRUE;
+
+       /* Register the handler for this particular GROUP interrupt source */
+       mddi_sharp_vsync_handler = handler;
+       mddi_sharp_vsync_handler_arg = arg;
+
+       /* Restore interrupts */
+       spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+       /* INTFREE(); */
+
+       if (error)
+               MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
+
+       /* Enable the vsync wakeup */
+       mddi_queue_register_write(REG_INTR, 0x8100, FALSE, 0);
+
+       mddi_sharp_vsync_attempts = 1;
+       mddi_vsync_detect_enabled = TRUE;
+}                              /* mddi_sharp_vsync_set_handler */
+
+static int mddi_sharp_lcd_on(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+
+       mfd = platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       if (mfd->panel.id == SHARP_QVGA_PRIM)
+               mddi_sharp_prim_lcd_init();
+       else
+               mddi_sharp_sub_lcd_init();
+
+       return 0;
+}
+
+static int mddi_sharp_lcd_off(struct platform_device *pdev)
+{
+       mddi_sharp_lcd_powerdown();
+       return 0;
+}
+
+static int __init mddi_sharp_probe(struct platform_device *pdev)
+{
+       if (pdev->id == 0) {
+               mddi_sharp_pdata = pdev->dev.platform_data;
+               return 0;
+       }
+
+       msm_fb_add_device(pdev);
+
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = mddi_sharp_probe,
+       .driver = {
+               .name   = "mddi_sharp_qvga",
+       },
+};
+
+static struct msm_fb_panel_data mddi_sharp_panel_data0 = {
+       .on = mddi_sharp_lcd_on,
+       .off = mddi_sharp_lcd_off,
+       .set_backlight = mddi_sharp_lcd_set_backlight,
+       .set_vsync_notifier = mddi_sharp_vsync_set_handler,
+};
+
+static struct platform_device this_device_0 = {
+       .name   = "mddi_sharp_qvga",
+       .id     = SHARP_QVGA_PRIM,
+       .dev    = {
+               .platform_data = &mddi_sharp_panel_data0,
+       }
+};
+
+static struct msm_fb_panel_data mddi_sharp_panel_data1 = {
+       .on = mddi_sharp_lcd_on,
+       .off = mddi_sharp_lcd_off,
+};
+
+static struct platform_device this_device_1 = {
+       .name   = "mddi_sharp_qvga",
+       .id     = SHARP_128X128_SECD,
+       .dev    = {
+               .platform_data = &mddi_sharp_panel_data1,
+       }
+};
+
+static int __init mddi_sharp_init(void)
+{
+       int ret;
+       struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+       u32 id;
+
+       ret = msm_fb_detect_client("mddi_sharp_qvga");
+       if (ret == -ENODEV)
+               return 0;
+
+       if (ret) {
+               id = mddi_get_client_id();
+
+               if (((id >> 16) != 0x0) || ((id & 0xffff) != 0x8835))
+                       return 0;
+       }
+#endif
+       if (mddi_host_core_version > 8) {
+               /* can use faster refresh with newer hw revisions */
+               mddi_sharp_debug_60hz_refresh = TRUE;
+
+               /* Timing variables for tracking vsync */
+               /* dot_clock = 6.00MHz
+                * horizontal count = 296
+                * vertical count = 338
+                * refresh rate = 6000000/(296+338) = 60Hz
+                */
+               mddi_sharp_rows_per_second = 20270;     /* 6000000/296 */
+               mddi_sharp_rows_per_refresh = 338;
+               mddi_sharp_usecs_per_refresh = 16674;   /* (296+338)/6000000 */
+       } else {
+               /* Timing variables for tracking vsync */
+               /* dot_clock = 5.20MHz
+                * horizontal count = 376
+                * vertical count = 338
+                * refresh rate = 5200000/(376+338) = 41Hz
+                */
+               mddi_sharp_rows_per_second = 13830;     /* 5200000/376 */
+               mddi_sharp_rows_per_refresh = 338;
+               mddi_sharp_usecs_per_refresh = 24440;   /* (376+338)/5200000 */
+       }
+
+       ret = platform_driver_register(&this_driver);
+       if (!ret) {
+               pinfo = &mddi_sharp_panel_data0.panel_info;
+               pinfo->xres = 240;
+               pinfo->yres = 320;
+               pinfo->type = MDDI_PANEL;
+               pinfo->pdest = DISPLAY_1;
+               pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+               pinfo->wait_cycle = 0;
+               pinfo->bpp = 18;
+               pinfo->fb_num = 2;
+               pinfo->clk_rate = 122880000;
+               pinfo->clk_min = 120000000;
+               pinfo->clk_max = 125000000;
+               pinfo->lcd.vsync_enable = TRUE;
+               pinfo->lcd.refx100 =
+                       (mddi_sharp_rows_per_second * 100) /
+                       mddi_sharp_rows_per_refresh;
+               pinfo->lcd.v_back_porch = 12;
+               pinfo->lcd.v_front_porch = 6;
+               pinfo->lcd.v_pulse_width = 0;
+               pinfo->lcd.hw_vsync_mode = FALSE;
+               pinfo->lcd.vsync_notifier_period = (1 * HZ);
+               pinfo->bl_max = 7;
+               pinfo->bl_min = 1;
+
+               ret = platform_device_register(&this_device_0);
+               if (ret)
+                       platform_driver_unregister(&this_driver);
+
+               pinfo = &mddi_sharp_panel_data1.panel_info;
+               pinfo->xres = 128;
+               pinfo->yres = 128;
+               pinfo->type = MDDI_PANEL;
+               pinfo->pdest = DISPLAY_2;
+               pinfo->mddi.vdopkt = 0x400;
+               pinfo->wait_cycle = 0;
+               pinfo->bpp = 18;
+               pinfo->clk_rate = 122880000;
+               pinfo->clk_min = 120000000;
+               pinfo->clk_max = 125000000;
+               pinfo->fb_num = 2;
+
+               ret = platform_device_register(&this_device_1);
+               if (ret) {
+                       platform_device_unregister(&this_device_0);
+                       platform_driver_unregister(&this_driver);
+               }
+       }
+
+       if (!ret)
+               mddi_lcd.vsync_detected = mddi_sharp_lcd_vsync_detected;
+
+       return ret;
+}
+
+module_init(mddi_sharp_init);
diff --git a/drivers/staging/msm/mddi_toshiba.c b/drivers/staging/msm/mddi_toshiba.c
new file mode 100644 (file)
index 0000000..e96342d
--- /dev/null
@@ -0,0 +1,1741 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+#define TM_GET_DID(id) ((id) & 0xff)
+#define TM_GET_PID(id) (((id) & 0xff00)>>8)
+
+#define MDDI_CLIENT_CORE_BASE  0x108000
+#define LCD_CONTROL_BLOCK_BASE 0x110000
+#define SPI_BLOCK_BASE         0x120000
+#define PWM_BLOCK_BASE         0x140000
+#define SYSTEM_BLOCK1_BASE     0x160000
+
+#define TTBUSSEL    (MDDI_CLIENT_CORE_BASE|0x18)
+#define DPSET0      (MDDI_CLIENT_CORE_BASE|0x1C)
+#define DPSET1      (MDDI_CLIENT_CORE_BASE|0x20)
+#define DPSUS       (MDDI_CLIENT_CORE_BASE|0x24)
+#define DPRUN       (MDDI_CLIENT_CORE_BASE|0x28)
+#define SYSCKENA    (MDDI_CLIENT_CORE_BASE|0x2C)
+
+#define BITMAP0     (MDDI_CLIENT_CORE_BASE|0x44)
+#define BITMAP1     (MDDI_CLIENT_CORE_BASE|0x48)
+#define BITMAP2     (MDDI_CLIENT_CORE_BASE|0x4C)
+#define BITMAP3     (MDDI_CLIENT_CORE_BASE|0x50)
+#define BITMAP4     (MDDI_CLIENT_CORE_BASE|0x54)
+
+#define SRST        (LCD_CONTROL_BLOCK_BASE|0x00)
+#define PORT_ENB    (LCD_CONTROL_BLOCK_BASE|0x04)
+#define START       (LCD_CONTROL_BLOCK_BASE|0x08)
+#define PORT        (LCD_CONTROL_BLOCK_BASE|0x0C)
+
+#define INTFLG      (LCD_CONTROL_BLOCK_BASE|0x18)
+#define INTMSK      (LCD_CONTROL_BLOCK_BASE|0x1C)
+#define MPLFBUF     (LCD_CONTROL_BLOCK_BASE|0x20)
+
+#define PXL         (LCD_CONTROL_BLOCK_BASE|0x30)
+#define HCYCLE      (LCD_CONTROL_BLOCK_BASE|0x34)
+#define HSW         (LCD_CONTROL_BLOCK_BASE|0x38)
+#define HDE_START   (LCD_CONTROL_BLOCK_BASE|0x3C)
+#define HDE_SIZE    (LCD_CONTROL_BLOCK_BASE|0x40)
+#define VCYCLE      (LCD_CONTROL_BLOCK_BASE|0x44)
+#define VSW         (LCD_CONTROL_BLOCK_BASE|0x48)
+#define VDE_START   (LCD_CONTROL_BLOCK_BASE|0x4C)
+#define VDE_SIZE    (LCD_CONTROL_BLOCK_BASE|0x50)
+#define WAKEUP      (LCD_CONTROL_BLOCK_BASE|0x54)
+#define REGENB      (LCD_CONTROL_BLOCK_BASE|0x5C)
+#define VSYNIF      (LCD_CONTROL_BLOCK_BASE|0x60)
+#define WRSTB       (LCD_CONTROL_BLOCK_BASE|0x64)
+#define RDSTB       (LCD_CONTROL_BLOCK_BASE|0x68)
+#define ASY_DATA    (LCD_CONTROL_BLOCK_BASE|0x6C)
+#define ASY_DATB    (LCD_CONTROL_BLOCK_BASE|0x70)
+#define ASY_DATC    (LCD_CONTROL_BLOCK_BASE|0x74)
+#define ASY_DATD    (LCD_CONTROL_BLOCK_BASE|0x78)
+#define ASY_DATE    (LCD_CONTROL_BLOCK_BASE|0x7C)
+#define ASY_DATF    (LCD_CONTROL_BLOCK_BASE|0x80)
+#define ASY_DATG    (LCD_CONTROL_BLOCK_BASE|0x84)
+#define ASY_DATH    (LCD_CONTROL_BLOCK_BASE|0x88)
+#define ASY_CMDSET  (LCD_CONTROL_BLOCK_BASE|0x8C)
+#define MONI        (LCD_CONTROL_BLOCK_BASE|0xB0)
+#define VPOS        (LCD_CONTROL_BLOCK_BASE|0xC0)
+
+#define SSICTL      (SPI_BLOCK_BASE|0x00)
+#define SSITIME     (SPI_BLOCK_BASE|0x04)
+#define SSITX       (SPI_BLOCK_BASE|0x08)
+#define SSIINTS     (SPI_BLOCK_BASE|0x14)
+
+#define TIMER0LOAD    (PWM_BLOCK_BASE|0x00)
+#define TIMER0CTRL    (PWM_BLOCK_BASE|0x08)
+#define PWM0OFF       (PWM_BLOCK_BASE|0x1C)
+#define TIMER1LOAD    (PWM_BLOCK_BASE|0x20)
+#define TIMER1CTRL    (PWM_BLOCK_BASE|0x28)
+#define PWM1OFF       (PWM_BLOCK_BASE|0x3C)
+#define TIMER2LOAD    (PWM_BLOCK_BASE|0x40)
+#define TIMER2CTRL    (PWM_BLOCK_BASE|0x48)
+#define PWM2OFF       (PWM_BLOCK_BASE|0x5C)
+#define PWMCR         (PWM_BLOCK_BASE|0x68)
+
+#define GPIOIS      (GPIO_BLOCK_BASE|0x08)
+#define GPIOIEV     (GPIO_BLOCK_BASE|0x10)
+#define GPIOIC      (GPIO_BLOCK_BASE|0x20)
+
+#define WKREQ       (SYSTEM_BLOCK1_BASE|0x00)
+#define CLKENB      (SYSTEM_BLOCK1_BASE|0x04)
+#define DRAMPWR     (SYSTEM_BLOCK1_BASE|0x08)
+#define INTMASK     (SYSTEM_BLOCK1_BASE|0x0C)
+#define CNT_DIS     (SYSTEM_BLOCK1_BASE|0x10)
+
+typedef enum {
+       TOSHIBA_STATE_OFF,
+       TOSHIBA_STATE_PRIM_SEC_STANDBY,
+       TOSHIBA_STATE_PRIM_SEC_READY,
+       TOSHIBA_STATE_PRIM_NORMAL_MODE,
+       TOSHIBA_STATE_SEC_NORMAL_MODE
+} mddi_toshiba_state_t;
+
+static uint32 mddi_toshiba_curr_vpos;
+static boolean mddi_toshiba_monitor_refresh_value = FALSE;
+static boolean mddi_toshiba_report_refresh_measurements = FALSE;
+
+boolean mddi_toshiba_61Hz_refresh = TRUE;
+
+/* Modifications to timing to increase refresh rate to > 60Hz.
+ *   20MHz dot clock.
+ *   646 total rows.
+ *   506 total columns.
+ *   refresh rate = 61.19Hz
+ */
+static uint32 mddi_toshiba_rows_per_second = 39526;
+static uint32 mddi_toshiba_usecs_per_refresh = 16344;
+static uint32 mddi_toshiba_rows_per_refresh = 646;
+extern boolean mddi_vsync_detect_enabled;
+
+static msm_fb_vsync_handler_type mddi_toshiba_vsync_handler;
+static void *mddi_toshiba_vsync_handler_arg;
+static uint16 mddi_toshiba_vsync_attempts;
+
+static mddi_toshiba_state_t toshiba_state = TOSHIBA_STATE_OFF;
+
+static struct msm_panel_common_pdata *mddi_toshiba_pdata;
+
+static int mddi_toshiba_lcd_on(struct platform_device *pdev);
+static int mddi_toshiba_lcd_off(struct platform_device *pdev);
+
+static void mddi_toshiba_state_transition(mddi_toshiba_state_t a,
+                                         mddi_toshiba_state_t b)
+{
+       if (toshiba_state != a) {
+               MDDI_MSG_ERR("toshiba state trans. (%d->%d) found %d\n", a, b,
+                            toshiba_state);
+       }
+       toshiba_state = b;
+}
+
+#define GORDON_REG_IMGCTL1      0x10   /* Image interface control 1   */
+#define GORDON_REG_IMGCTL2      0x11   /* Image interface control 2   */
+#define GORDON_REG_IMGSET1      0x12   /* Image interface settings 1  */
+#define GORDON_REG_IMGSET2      0x13   /* Image interface settings 2  */
+#define GORDON_REG_IVBP1        0x14   /* DM0: Vert back porch        */
+#define GORDON_REG_IHBP1        0x15   /* DM0: Horiz back porch       */
+#define GORDON_REG_IVNUM1       0x16   /* DM0: Num of vert lines      */
+#define GORDON_REG_IHNUM1       0x17   /* DM0: Num of pixels per line */
+#define GORDON_REG_IVBP2        0x18   /* DM1: Vert back porch        */
+#define GORDON_REG_IHBP2        0x19   /* DM1: Horiz back porch       */
+#define GORDON_REG_IVNUM2       0x1A   /* DM1: Num of vert lines      */
+#define GORDON_REG_IHNUM2       0x1B   /* DM1: Num of pixels per line */
+#define GORDON_REG_LCDIFCTL1    0x30   /* LCD interface control 1     */
+#define GORDON_REG_VALTRAN      0x31   /* LCD IF ctl: VALTRAN sync flag */
+#define GORDON_REG_AVCTL        0x33
+#define GORDON_REG_LCDIFCTL2    0x34   /* LCD interface control 2     */
+#define GORDON_REG_LCDIFCTL3    0x35   /* LCD interface control 3     */
+#define GORDON_REG_LCDIFSET1    0x36   /* LCD interface settings 1    */
+#define GORDON_REG_PCCTL        0x3C
+#define GORDON_REG_TPARAM1      0x40
+#define GORDON_REG_TLCDIF1      0x41
+#define GORDON_REG_TSSPB_ST1    0x42
+#define GORDON_REG_TSSPB_ED1    0x43
+#define GORDON_REG_TSCK_ST1     0x44
+#define GORDON_REG_TSCK_WD1     0x45
+#define GORDON_REG_TGSPB_VST1   0x46
+#define GORDON_REG_TGSPB_VED1   0x47
+#define GORDON_REG_TGSPB_CH1    0x48
+#define GORDON_REG_TGCK_ST1     0x49
+#define GORDON_REG_TGCK_ED1     0x4A
+#define GORDON_REG_TPCTL_ST1    0x4B
+#define GORDON_REG_TPCTL_ED1    0x4C
+#define GORDON_REG_TPCHG_ED1    0x4D
+#define GORDON_REG_TCOM_CH1     0x4E
+#define GORDON_REG_THBP1        0x4F
+#define GORDON_REG_TPHCTL1      0x50
+#define GORDON_REG_EVPH1        0x51
+#define GORDON_REG_EVPL1        0x52
+#define GORDON_REG_EVNH1        0x53
+#define GORDON_REG_EVNL1        0x54
+#define GORDON_REG_TBIAS1       0x55
+#define GORDON_REG_TPARAM2      0x56
+#define GORDON_REG_TLCDIF2      0x57
+#define GORDON_REG_TSSPB_ST2    0x58
+#define GORDON_REG_TSSPB_ED2    0x59
+#define GORDON_REG_TSCK_ST2     0x5A
+#define GORDON_REG_TSCK_WD2     0x5B
+#define GORDON_REG_TGSPB_VST2   0x5C
+#define GORDON_REG_TGSPB_VED2   0x5D
+#define GORDON_REG_TGSPB_CH2    0x5E
+#define GORDON_REG_TGCK_ST2     0x5F
+#define GORDON_REG_TGCK_ED2     0x60
+#define GORDON_REG_TPCTL_ST2    0x61
+#define GORDON_REG_TPCTL_ED2    0x62
+#define GORDON_REG_TPCHG_ED2    0x63
+#define GORDON_REG_TCOM_CH2     0x64
+#define GORDON_REG_THBP2        0x65
+#define GORDON_REG_TPHCTL2      0x66
+#define GORDON_REG_EVPH2        0x67
+#define GORDON_REG_EVPL2        0x68
+#define GORDON_REG_EVNH2        0x69
+#define GORDON_REG_EVNL2        0x6A
+#define GORDON_REG_TBIAS2       0x6B
+#define GORDON_REG_POWCTL       0x80
+#define GORDON_REG_POWOSC1      0x81
+#define GORDON_REG_POWOSC2      0x82
+#define GORDON_REG_POWSET       0x83
+#define GORDON_REG_POWTRM1      0x85
+#define GORDON_REG_POWTRM2      0x86
+#define GORDON_REG_POWTRM3      0x87
+#define GORDON_REG_POWTRMSEL    0x88
+#define GORDON_REG_POWHIZ       0x89
+
+void serigo(uint16 reg, uint8 data)
+{
+       uint32 mddi_val = 0;
+       mddi_queue_register_read(SSIINTS, &mddi_val, TRUE, 0);
+       if (mddi_val & (1 << 8))
+               mddi_wait(1);
+       /* No De-assert of CS and send 2 bytes */
+       mddi_val = 0x90000 | ((0x00FF & reg) << 8) | data;
+       mddi_queue_register_write(SSITX, mddi_val, TRUE, 0);
+}
+
+void gordon_init(void)
+{
+       /* Image interface settings ***/
+       serigo(GORDON_REG_IMGCTL2, 0x00);
+       serigo(GORDON_REG_IMGSET1, 0x01);
+
+       /* Exchange the RGB signal for J510(Softbank mobile) */
+       serigo(GORDON_REG_IMGSET2, 0x12);
+       serigo(GORDON_REG_LCDIFSET1, 0x00);
+       mddi_wait(2);
+
+       /* Pre-charge settings */
+       serigo(GORDON_REG_PCCTL, 0x09);
+       serigo(GORDON_REG_LCDIFCTL2, 0x1B);
+       mddi_wait(1);
+}
+
+void gordon_disp_on(void)
+{
+       /*gordon_dispmode setting */
+       /*VGA settings */
+       serigo(GORDON_REG_TPARAM1, 0x30);
+       serigo(GORDON_REG_TLCDIF1, 0x00);
+       serigo(GORDON_REG_TSSPB_ST1, 0x8B);
+       serigo(GORDON_REG_TSSPB_ED1, 0x93);
+       mddi_wait(2);
+       serigo(GORDON_REG_TSCK_ST1, 0x88);
+       serigo(GORDON_REG_TSCK_WD1, 0x00);
+       serigo(GORDON_REG_TGSPB_VST1, 0x01);
+       serigo(GORDON_REG_TGSPB_VED1, 0x02);
+       mddi_wait(2);
+       serigo(GORDON_REG_TGSPB_CH1, 0x5E);
+       serigo(GORDON_REG_TGCK_ST1, 0x80);
+       serigo(GORDON_REG_TGCK_ED1, 0x3C);
+       serigo(GORDON_REG_TPCTL_ST1, 0x50);
+       mddi_wait(2);
+       serigo(GORDON_REG_TPCTL_ED1, 0x74);
+       serigo(GORDON_REG_TPCHG_ED1, 0x78);
+       serigo(GORDON_REG_TCOM_CH1, 0x50);
+       serigo(GORDON_REG_THBP1, 0x84);
+       mddi_wait(2);
+       serigo(GORDON_REG_TPHCTL1, 0x00);
+       serigo(GORDON_REG_EVPH1, 0x70);
+       serigo(GORDON_REG_EVPL1, 0x64);
+       serigo(GORDON_REG_EVNH1, 0x56);
+       mddi_wait(2);
+       serigo(GORDON_REG_EVNL1, 0x48);
+       serigo(GORDON_REG_TBIAS1, 0x88);
+       mddi_wait(2);
+       serigo(GORDON_REG_TPARAM2, 0x28);
+       serigo(GORDON_REG_TLCDIF2, 0x14);
+       serigo(GORDON_REG_TSSPB_ST2, 0x49);
+       serigo(GORDON_REG_TSSPB_ED2, 0x4B);
+       mddi_wait(2);
+       serigo(GORDON_REG_TSCK_ST2, 0x4A);
+       serigo(GORDON_REG_TSCK_WD2, 0x02);
+       serigo(GORDON_REG_TGSPB_VST2, 0x02);
+       serigo(GORDON_REG_TGSPB_VED2, 0x03);
+       mddi_wait(2);
+       serigo(GORDON_REG_TGSPB_CH2, 0x2F);
+       serigo(GORDON_REG_TGCK_ST2, 0x40);
+       serigo(GORDON_REG_TGCK_ED2, 0x1E);
+       serigo(GORDON_REG_TPCTL_ST2, 0x2C);
+       mddi_wait(2);
+       serigo(GORDON_REG_TPCTL_ED2, 0x3A);
+       serigo(GORDON_REG_TPCHG_ED2, 0x3C);
+       serigo(GORDON_REG_TCOM_CH2, 0x28);
+       serigo(GORDON_REG_THBP2, 0x4D);
+       mddi_wait(2);
+       serigo(GORDON_REG_TPHCTL2, 0x1A);
+       mddi_wait(2);
+       serigo(GORDON_REG_IVBP1, 0x02);
+       serigo(GORDON_REG_IHBP1, 0x90);
+       serigo(GORDON_REG_IVNUM1, 0xA0);
+       serigo(GORDON_REG_IHNUM1, 0x78);
+       mddi_wait(2);
+       serigo(GORDON_REG_IVBP2, 0x02);
+       serigo(GORDON_REG_IHBP2, 0x48);
+       serigo(GORDON_REG_IVNUM2, 0x50);
+       serigo(GORDON_REG_IHNUM2, 0x3C);
+       mddi_wait(2);
+       serigo(GORDON_REG_POWCTL, 0x03);
+       mddi_wait(15);
+       serigo(GORDON_REG_POWCTL, 0x07);
+       mddi_wait(15);
+       serigo(GORDON_REG_POWCTL, 0x0F);
+       mddi_wait(15);
+       serigo(GORDON_REG_AVCTL, 0x03);
+       mddi_wait(15);
+       serigo(GORDON_REG_POWCTL, 0x1F);
+       mddi_wait(15);
+       serigo(GORDON_REG_POWCTL, 0x5F);
+       mddi_wait(15);
+       serigo(GORDON_REG_POWCTL, 0x7F);
+       mddi_wait(15);
+       serigo(GORDON_REG_LCDIFCTL1, 0x02);
+       mddi_wait(15);
+       serigo(GORDON_REG_IMGCTL1, 0x00);
+       mddi_wait(15);
+       serigo(GORDON_REG_LCDIFCTL3, 0x00);
+       mddi_wait(15);
+       serigo(GORDON_REG_VALTRAN, 0x01);
+       mddi_wait(15);
+       serigo(GORDON_REG_LCDIFCTL1, 0x03);
+       serigo(GORDON_REG_LCDIFCTL1, 0x03);
+       mddi_wait(1);
+}
+
+void gordon_disp_off(void)
+{
+       serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+       serigo(GORDON_REG_VALTRAN, 0x01);
+       serigo(GORDON_REG_LCDIFCTL1, 0x02);
+       serigo(GORDON_REG_LCDIFCTL3, 0x01);
+       mddi_wait(20);
+       serigo(GORDON_REG_VALTRAN, 0x01);
+       serigo(GORDON_REG_IMGCTL1, 0x01);
+       serigo(GORDON_REG_LCDIFCTL1, 0x00);
+       mddi_wait(20);
+       serigo(GORDON_REG_POWCTL, 0x1F);
+       mddi_wait(40);
+       serigo(GORDON_REG_POWCTL, 0x07);
+       mddi_wait(40);
+       serigo(GORDON_REG_POWCTL, 0x03);
+       mddi_wait(40);
+       serigo(GORDON_REG_POWCTL, 0x00);
+       mddi_wait(40);
+}
+
+void gordon_disp_init(void)
+{
+       gordon_init();
+       mddi_wait(20);
+       gordon_disp_on();
+}
+
+static void toshiba_common_initial_setup(struct msm_fb_data_type *mfd)
+{
+       if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) {
+               write_client_reg(DPSET0    , 0x4bec0066, TRUE);
+               write_client_reg(DPSET1    , 0x00000113, TRUE);
+               write_client_reg(DPSUS     , 0x00000000, TRUE);
+               write_client_reg(DPRUN     , 0x00000001, TRUE);
+               mddi_wait(5);
+               write_client_reg(SYSCKENA  , 0x00000001, TRUE);
+               write_client_reg(CLKENB    , 0x0000a0e9, TRUE);
+
+               write_client_reg(GPIODATA  , 0x03FF0000, TRUE);
+               write_client_reg(GPIODIR   , 0x0000024D, TRUE);
+               write_client_reg(GPIOSEL   , 0x00000173, TRUE);
+               write_client_reg(GPIOPC    , 0x03C300C0, TRUE);
+               write_client_reg(WKREQ     , 0x00000000, TRUE);
+               write_client_reg(GPIOIS    , 0x00000000, TRUE);
+               write_client_reg(GPIOIEV   , 0x00000001, TRUE);
+               write_client_reg(GPIOIC    , 0x000003FF, TRUE);
+               write_client_reg(GPIODATA  , 0x00040004, TRUE);
+
+               write_client_reg(GPIODATA  , 0x00080008, TRUE);
+               write_client_reg(DRAMPWR   , 0x00000001, TRUE);
+               write_client_reg(CLKENB    , 0x0000a0eb, TRUE);
+               write_client_reg(PWMCR     , 0x00000000, TRUE);
+               mddi_wait(1);
+
+               write_client_reg(SSICTL    , 0x00060399, TRUE);
+               write_client_reg(SSITIME   , 0x00000100, TRUE);
+               write_client_reg(CNT_DIS   , 0x00000002, TRUE);
+               write_client_reg(SSICTL    , 0x0006039b, TRUE);
+
+               write_client_reg(SSITX     , 0x00000000, TRUE);
+               mddi_wait(7);
+               write_client_reg(SSITX     , 0x00000000, TRUE);
+               mddi_wait(7);
+               write_client_reg(SSITX     , 0x00000000, TRUE);
+               mddi_wait(7);
+
+               write_client_reg(SSITX     , 0x000800BA, TRUE);
+               write_client_reg(SSITX     , 0x00000111, TRUE);
+               write_client_reg(SSITX     , 0x00080036, TRUE);
+               write_client_reg(SSITX     , 0x00000100, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x0008003A, TRUE);
+               write_client_reg(SSITX     , 0x00000160, TRUE);
+               write_client_reg(SSITX     , 0x000800B1, TRUE);
+               write_client_reg(SSITX     , 0x0000015D, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800B2, TRUE);
+               write_client_reg(SSITX     , 0x00000133, TRUE);
+               write_client_reg(SSITX     , 0x000800B3, TRUE);
+               write_client_reg(SSITX     , 0x00000122, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800B4, TRUE);
+               write_client_reg(SSITX     , 0x00000102, TRUE);
+               write_client_reg(SSITX     , 0x000800B5, TRUE);
+               write_client_reg(SSITX     , 0x0000011E, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800B6, TRUE);
+               write_client_reg(SSITX     , 0x00000127, TRUE);
+               write_client_reg(SSITX     , 0x000800B7, TRUE);
+               write_client_reg(SSITX     , 0x00000103, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800B9, TRUE);
+               write_client_reg(SSITX     , 0x00000124, TRUE);
+               write_client_reg(SSITX     , 0x000800BD, TRUE);
+               write_client_reg(SSITX     , 0x000001A1, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800BB, TRUE);
+               write_client_reg(SSITX     , 0x00000100, TRUE);
+               write_client_reg(SSITX     , 0x000800BF, TRUE);
+               write_client_reg(SSITX     , 0x00000101, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800BE, TRUE);
+               write_client_reg(SSITX     , 0x00000100, TRUE);
+               write_client_reg(SSITX     , 0x000800C0, TRUE);
+               write_client_reg(SSITX     , 0x00000111, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800C1, TRUE);
+               write_client_reg(SSITX     , 0x00000111, TRUE);
+               write_client_reg(SSITX     , 0x000800C2, TRUE);
+               write_client_reg(SSITX     , 0x00000111, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800C3, TRUE);
+               write_client_reg(SSITX     , 0x00080132, TRUE);
+               write_client_reg(SSITX     , 0x00000132, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800C4, TRUE);
+               write_client_reg(SSITX     , 0x00080132, TRUE);
+               write_client_reg(SSITX     , 0x00000132, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800C5, TRUE);
+               write_client_reg(SSITX     , 0x00080132, TRUE);
+               write_client_reg(SSITX     , 0x00000132, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800C6, TRUE);
+               write_client_reg(SSITX     , 0x00080132, TRUE);
+               write_client_reg(SSITX     , 0x00000132, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800C7, TRUE);
+               write_client_reg(SSITX     , 0x00080164, TRUE);
+               write_client_reg(SSITX     , 0x00000145, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800C8, TRUE);
+               write_client_reg(SSITX     , 0x00000144, TRUE);
+               write_client_reg(SSITX     , 0x000800C9, TRUE);
+               write_client_reg(SSITX     , 0x00000152, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800CA, TRUE);
+               write_client_reg(SSITX     , 0x00000100, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800EC, TRUE);
+               write_client_reg(SSITX     , 0x00080101, TRUE);
+               write_client_reg(SSITX     , 0x000001FC, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800CF, TRUE);
+               write_client_reg(SSITX     , 0x00000101, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800D0, TRUE);
+               write_client_reg(SSITX     , 0x00080110, TRUE);
+               write_client_reg(SSITX     , 0x00000104, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800D1, TRUE);
+               write_client_reg(SSITX     , 0x00000101, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800D2, TRUE);
+               write_client_reg(SSITX     , 0x00080100, TRUE);
+               write_client_reg(SSITX     , 0x00000128, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800D3, TRUE);
+               write_client_reg(SSITX     , 0x00080100, TRUE);
+               write_client_reg(SSITX     , 0x00000128, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800D4, TRUE);
+               write_client_reg(SSITX     , 0x00080126, TRUE);
+               write_client_reg(SSITX     , 0x000001A4, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800D5, TRUE);
+               write_client_reg(SSITX     , 0x00000120, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800EF, TRUE);
+               write_client_reg(SSITX     , 0x00080132, TRUE);
+               write_client_reg(SSITX     , 0x00000100, TRUE);
+               mddi_wait(1);
+
+               write_client_reg(BITMAP0   , 0x032001E0, TRUE);
+               write_client_reg(BITMAP1   , 0x032001E0, TRUE);
+               write_client_reg(BITMAP2   , 0x014000F0, TRUE);
+               write_client_reg(BITMAP3   , 0x014000F0, TRUE);
+               write_client_reg(BITMAP4   , 0x014000F0, TRUE);
+               write_client_reg(CLKENB    , 0x0000A1EB, TRUE);
+               write_client_reg(PORT_ENB  , 0x00000001, TRUE);
+               write_client_reg(PORT      , 0x00000004, TRUE);
+               write_client_reg(PXL       , 0x00000002, TRUE);
+               write_client_reg(MPLFBUF   , 0x00000000, TRUE);
+               write_client_reg(HCYCLE    , 0x000000FD, TRUE);
+               write_client_reg(HSW       , 0x00000003, TRUE);
+               write_client_reg(HDE_START , 0x00000007, TRUE);
+               write_client_reg(HDE_SIZE  , 0x000000EF, TRUE);
+               write_client_reg(VCYCLE    , 0x00000325, TRUE);
+               write_client_reg(VSW       , 0x00000001, TRUE);
+               write_client_reg(VDE_START , 0x00000003, TRUE);
+               write_client_reg(VDE_SIZE  , 0x0000031F, TRUE);
+               write_client_reg(START     , 0x00000001, TRUE);
+               mddi_wait(32);
+               write_client_reg(SSITX     , 0x000800BC, TRUE);
+               write_client_reg(SSITX     , 0x00000180, TRUE);
+               write_client_reg(SSITX     , 0x0008003B, TRUE);
+               write_client_reg(SSITX     , 0x00000100, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800B0, TRUE);
+               write_client_reg(SSITX     , 0x00000116, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x000800B8, TRUE);
+               write_client_reg(SSITX     , 0x000801FF, TRUE);
+               write_client_reg(SSITX     , 0x000001F5, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX     , 0x00000011, TRUE);
+               mddi_wait(5);
+               write_client_reg(SSITX     , 0x00000029, TRUE);
+               return;
+       }
+
+       if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+               write_client_reg(DPSET0, 0x4BEC0066, TRUE);
+               write_client_reg(DPSET1, 0x00000113, TRUE);
+               write_client_reg(DPSUS, 0x00000000, TRUE);
+               write_client_reg(DPRUN, 0x00000001, TRUE);
+               mddi_wait(14);
+               write_client_reg(SYSCKENA, 0x00000001, TRUE);
+               write_client_reg(CLKENB, 0x000000EF, TRUE);
+               write_client_reg(GPIO_BLOCK_BASE, 0x03FF0000, TRUE);
+               write_client_reg(GPIODIR, 0x0000024D, TRUE);
+               write_client_reg(SYSTEM_BLOCK2_BASE, 0x00000173, TRUE);
+               write_client_reg(GPIOPC, 0x03C300C0, TRUE);
+               write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000000, TRUE);
+               write_client_reg(GPIOIS, 0x00000000, TRUE);
+               write_client_reg(GPIOIEV, 0x00000001, TRUE);
+               write_client_reg(GPIOIC, 0x000003FF, TRUE);
+               write_client_reg(GPIO_BLOCK_BASE, 0x00060006, TRUE);
+               write_client_reg(GPIO_BLOCK_BASE, 0x00080008, TRUE);
+               write_client_reg(GPIO_BLOCK_BASE, 0x02000200, TRUE);
+               write_client_reg(DRAMPWR, 0x00000001, TRUE);
+               write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+               write_client_reg(PWM_BLOCK_BASE, 0x00001388, TRUE);
+               write_client_reg(PWM0OFF, 0x00001387, TRUE);
+               write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+               write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+               write_client_reg(PWM1OFF, 0x00001387, TRUE);
+               write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+               write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+               write_client_reg(PWMCR, 0x00000003, TRUE);
+               mddi_wait(1);
+               write_client_reg(SPI_BLOCK_BASE, 0x00063111, TRUE);
+               write_client_reg(SSITIME, 0x00000100, TRUE);
+               write_client_reg(SPI_BLOCK_BASE, 0x00063113, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX, 0x00000000, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX, 0x00000000, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX, 0x00000000, TRUE);
+               mddi_wait(1);
+               write_client_reg(CLKENB, 0x0000A1EF, TRUE);
+               write_client_reg(START, 0x00000000, TRUE);
+               write_client_reg(WRSTB, 0x0000003F, TRUE);
+               write_client_reg(RDSTB, 0x00000432, TRUE);
+               write_client_reg(PORT_ENB, 0x00000002, TRUE);
+               write_client_reg(VSYNIF, 0x00000000, TRUE);
+               write_client_reg(ASY_DATA, 0x80000000, TRUE);
+               write_client_reg(ASY_DATB, 0x00000001, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+               mddi_wait(10);
+               write_client_reg(ASY_DATA, 0x80000000, TRUE);
+               write_client_reg(ASY_DATB, 0x80000000, TRUE);
+               write_client_reg(ASY_DATC, 0x80000000, TRUE);
+               write_client_reg(ASY_DATD, 0x80000000, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+               write_client_reg(ASY_DATA, 0x80000007, TRUE);
+               write_client_reg(ASY_DATB, 0x00004005, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+               mddi_wait(20);
+               write_client_reg(ASY_DATA, 0x80000059, TRUE);
+               write_client_reg(ASY_DATB, 0x00000000, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+
+               write_client_reg(VSYNIF, 0x00000001, TRUE);
+               write_client_reg(PORT_ENB, 0x00000001, TRUE);
+       } else {
+               write_client_reg(DPSET0, 0x4BEC0066, TRUE);
+               write_client_reg(DPSET1, 0x00000113, TRUE);
+               write_client_reg(DPSUS, 0x00000000, TRUE);
+               write_client_reg(DPRUN, 0x00000001, TRUE);
+               mddi_wait(14);
+               write_client_reg(SYSCKENA, 0x00000001, TRUE);
+               write_client_reg(CLKENB, 0x000000EF, TRUE);
+               write_client_reg(GPIODATA, 0x03FF0000, TRUE);
+               write_client_reg(GPIODIR, 0x0000024D, TRUE);
+               write_client_reg(GPIOSEL, 0x00000173, TRUE);
+               write_client_reg(GPIOPC, 0x03C300C0, TRUE);
+               write_client_reg(WKREQ, 0x00000000, TRUE);
+               write_client_reg(GPIOIS, 0x00000000, TRUE);
+               write_client_reg(GPIOIEV, 0x00000001, TRUE);
+               write_client_reg(GPIOIC, 0x000003FF, TRUE);
+               write_client_reg(GPIODATA, 0x00060006, TRUE);
+               write_client_reg(GPIODATA, 0x00080008, TRUE);
+               write_client_reg(GPIODATA, 0x02000200, TRUE);
+
+               if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA) {
+                       mddi_wait(400);
+                       write_client_reg(DRAMPWR, 0x00000001, TRUE);
+
+                       write_client_reg(CNT_DIS, 0x00000002, TRUE);
+                       write_client_reg(BITMAP0, 0x01E00320, TRUE);
+                       write_client_reg(PORT_ENB, 0x00000001, TRUE);
+                       write_client_reg(PORT, 0x00000004, TRUE);
+                       write_client_reg(PXL, 0x0000003A, TRUE);
+                       write_client_reg(MPLFBUF, 0x00000000, TRUE);
+                       write_client_reg(HCYCLE, 0x00000253, TRUE);
+                       write_client_reg(HSW, 0x00000003, TRUE);
+                       write_client_reg(HDE_START, 0x00000017, TRUE);
+                       write_client_reg(HDE_SIZE, 0x0000018F, TRUE);
+                       write_client_reg(VCYCLE, 0x000001FF, TRUE);
+                       write_client_reg(VSW, 0x00000001, TRUE);
+                       write_client_reg(VDE_START, 0x00000003, TRUE);
+                       write_client_reg(VDE_SIZE, 0x000001DF, TRUE);
+                       write_client_reg(START, 0x00000001, TRUE);
+                       mddi_wait(1);
+                       write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+                       write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+                       write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+                       write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+                       write_client_reg(PWM1OFF, 0x00000087, TRUE);
+               } else {
+                       write_client_reg(DRAMPWR, 0x00000001, TRUE);
+                       write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+                       write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+                       write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+                       write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+                       write_client_reg(PWM1OFF, 0x00001387, TRUE);
+               }
+
+               write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+               write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+               write_client_reg(PWMCR, 0x00000003, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSICTL, 0x00000799, TRUE);
+               write_client_reg(SSITIME, 0x00000100, TRUE);
+               write_client_reg(SSICTL, 0x0000079b, TRUE);
+               write_client_reg(SSITX, 0x00000000, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX, 0x00000000, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX, 0x00000000, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX, 0x000800BA, TRUE);
+               write_client_reg(SSITX, 0x00000111, TRUE);
+               write_client_reg(SSITX, 0x00080036, TRUE);
+               write_client_reg(SSITX, 0x00000100, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800BB, TRUE);
+               write_client_reg(SSITX, 0x00000100, TRUE);
+               write_client_reg(SSITX, 0x0008003A, TRUE);
+               write_client_reg(SSITX, 0x00000160, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800BF, TRUE);
+               write_client_reg(SSITX, 0x00000100, TRUE);
+               write_client_reg(SSITX, 0x000800B1, TRUE);
+               write_client_reg(SSITX, 0x0000015D, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800B2, TRUE);
+               write_client_reg(SSITX, 0x00000133, TRUE);
+               write_client_reg(SSITX, 0x000800B3, TRUE);
+               write_client_reg(SSITX, 0x00000122, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800B4, TRUE);
+               write_client_reg(SSITX, 0x00000102, TRUE);
+               write_client_reg(SSITX, 0x000800B5, TRUE);
+               write_client_reg(SSITX, 0x0000011F, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800B6, TRUE);
+               write_client_reg(SSITX, 0x00000128, TRUE);
+               write_client_reg(SSITX, 0x000800B7, TRUE);
+               write_client_reg(SSITX, 0x00000103, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800B9, TRUE);
+               write_client_reg(SSITX, 0x00000120, TRUE);
+               write_client_reg(SSITX, 0x000800BD, TRUE);
+               write_client_reg(SSITX, 0x00000102, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800BE, TRUE);
+               write_client_reg(SSITX, 0x00000100, TRUE);
+               write_client_reg(SSITX, 0x000800C0, TRUE);
+               write_client_reg(SSITX, 0x00000111, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800C1, TRUE);
+               write_client_reg(SSITX, 0x00000111, TRUE);
+               write_client_reg(SSITX, 0x000800C2, TRUE);
+               write_client_reg(SSITX, 0x00000111, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800C3, TRUE);
+               write_client_reg(SSITX, 0x0008010A, TRUE);
+               write_client_reg(SSITX, 0x0000010A, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800C4, TRUE);
+               write_client_reg(SSITX, 0x00080160, TRUE);
+               write_client_reg(SSITX, 0x00000160, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800C5, TRUE);
+               write_client_reg(SSITX, 0x00080160, TRUE);
+               write_client_reg(SSITX, 0x00000160, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800C6, TRUE);
+               write_client_reg(SSITX, 0x00080160, TRUE);
+               write_client_reg(SSITX, 0x00000160, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800C7, TRUE);
+               write_client_reg(SSITX, 0x00080133, TRUE);
+               write_client_reg(SSITX, 0x00000143, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800C8, TRUE);
+               write_client_reg(SSITX, 0x00000144, TRUE);
+               write_client_reg(SSITX, 0x000800C9, TRUE);
+               write_client_reg(SSITX, 0x00000133, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800CA, TRUE);
+               write_client_reg(SSITX, 0x00000100, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800EC, TRUE);
+               write_client_reg(SSITX, 0x00080102, TRUE);
+               write_client_reg(SSITX, 0x00000118, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800CF, TRUE);
+               write_client_reg(SSITX, 0x00000101, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800D0, TRUE);
+               write_client_reg(SSITX, 0x00080110, TRUE);
+               write_client_reg(SSITX, 0x00000104, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800D1, TRUE);
+               write_client_reg(SSITX, 0x00000101, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800D2, TRUE);
+               write_client_reg(SSITX, 0x00080100, TRUE);
+               write_client_reg(SSITX, 0x0000013A, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800D3, TRUE);
+               write_client_reg(SSITX, 0x00080100, TRUE);
+               write_client_reg(SSITX, 0x0000013A, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800D4, TRUE);
+               write_client_reg(SSITX, 0x00080124, TRUE);
+               write_client_reg(SSITX, 0x0000016E, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX, 0x000800D5, TRUE);
+               write_client_reg(SSITX, 0x00000124, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800ED, TRUE);
+               write_client_reg(SSITX, 0x00080101, TRUE);
+               write_client_reg(SSITX, 0x0000010A, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800D6, TRUE);
+               write_client_reg(SSITX, 0x00000101, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800D7, TRUE);
+               write_client_reg(SSITX, 0x00080110, TRUE);
+               write_client_reg(SSITX, 0x0000010A, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800D8, TRUE);
+               write_client_reg(SSITX, 0x00000101, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800D9, TRUE);
+               write_client_reg(SSITX, 0x00080100, TRUE);
+               write_client_reg(SSITX, 0x00000114, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800DE, TRUE);
+               write_client_reg(SSITX, 0x00080100, TRUE);
+               write_client_reg(SSITX, 0x00000114, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800DF, TRUE);
+               write_client_reg(SSITX, 0x00080112, TRUE);
+               write_client_reg(SSITX, 0x0000013F, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800E0, TRUE);
+               write_client_reg(SSITX, 0x0000010B, TRUE);
+               write_client_reg(SSITX, 0x000800E2, TRUE);
+               write_client_reg(SSITX, 0x00000101, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800E3, TRUE);
+               write_client_reg(SSITX, 0x00000136, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800E4, TRUE);
+               write_client_reg(SSITX, 0x00080100, TRUE);
+               write_client_reg(SSITX, 0x00000103, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800E5, TRUE);
+               write_client_reg(SSITX, 0x00080102, TRUE);
+               write_client_reg(SSITX, 0x00000104, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800E6, TRUE);
+               write_client_reg(SSITX, 0x00000103, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800E7, TRUE);
+               write_client_reg(SSITX, 0x00080104, TRUE);
+               write_client_reg(SSITX, 0x0000010A, TRUE);
+               mddi_wait(2);
+               write_client_reg(SSITX, 0x000800E8, TRUE);
+               write_client_reg(SSITX, 0x00000104, TRUE);
+               write_client_reg(CLKENB, 0x000001EF, TRUE);
+               write_client_reg(START, 0x00000000, TRUE);
+               write_client_reg(WRSTB, 0x0000003F, TRUE);
+               write_client_reg(RDSTB, 0x00000432, TRUE);
+               write_client_reg(PORT_ENB, 0x00000002, TRUE);
+               write_client_reg(VSYNIF, 0x00000000, TRUE);
+               write_client_reg(ASY_DATA, 0x80000000, TRUE);
+               write_client_reg(ASY_DATB, 0x00000001, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+               mddi_wait(10);
+               write_client_reg(ASY_DATA, 0x80000000, TRUE);
+               write_client_reg(ASY_DATB, 0x80000000, TRUE);
+               write_client_reg(ASY_DATC, 0x80000000, TRUE);
+               write_client_reg(ASY_DATD, 0x80000000, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+               write_client_reg(ASY_DATA, 0x80000007, TRUE);
+               write_client_reg(ASY_DATB, 0x00004005, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+               mddi_wait(20);
+               write_client_reg(ASY_DATA, 0x80000059, TRUE);
+               write_client_reg(ASY_DATB, 0x00000000, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+               write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+               write_client_reg(VSYNIF, 0x00000001, TRUE);
+               write_client_reg(PORT_ENB, 0x00000001, TRUE);
+       }
+
+       mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_STANDBY,
+                                     TOSHIBA_STATE_PRIM_SEC_READY);
+}
+
+static void toshiba_prim_start(struct msm_fb_data_type *mfd)
+{
+       if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+               return;
+
+       if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+               write_client_reg(BITMAP1, 0x01E000F0, TRUE);
+               write_client_reg(BITMAP2, 0x01E000F0, TRUE);
+               write_client_reg(BITMAP3, 0x01E000F0, TRUE);
+               write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+               write_client_reg(CLKENB, 0x000001EF, TRUE);
+               write_client_reg(PORT_ENB, 0x00000001, TRUE);
+               write_client_reg(PORT, 0x00000016, TRUE);
+               write_client_reg(PXL, 0x00000002, TRUE);
+               write_client_reg(MPLFBUF, 0x00000000, TRUE);
+               write_client_reg(HCYCLE, 0x00000185, TRUE);
+               write_client_reg(HSW, 0x00000018, TRUE);
+               write_client_reg(HDE_START, 0x0000004A, TRUE);
+               write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
+               write_client_reg(VCYCLE, 0x0000028E, TRUE);
+               write_client_reg(VSW, 0x00000004, TRUE);
+               write_client_reg(VDE_START, 0x00000009, TRUE);
+               write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
+               write_client_reg(START, 0x00000001, TRUE);
+               write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000002, TRUE);
+       } else{
+
+               write_client_reg(VSYNIF, 0x00000001, TRUE);
+               write_client_reg(PORT_ENB, 0x00000001, TRUE);
+               write_client_reg(BITMAP1, 0x01E000F0, TRUE);
+               write_client_reg(BITMAP2, 0x01E000F0, TRUE);
+               write_client_reg(BITMAP3, 0x01E000F0, TRUE);
+               write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+               write_client_reg(CLKENB, 0x000001EF, TRUE);
+               write_client_reg(PORT_ENB, 0x00000001, TRUE);
+               write_client_reg(PORT, 0x00000004, TRUE);
+               write_client_reg(PXL, 0x00000002, TRUE);
+               write_client_reg(MPLFBUF, 0x00000000, TRUE);
+
+               if (mddi_toshiba_61Hz_refresh) {
+                       write_client_reg(HCYCLE, 0x000000FC, TRUE);
+                       mddi_toshiba_rows_per_second = 39526;
+                       mddi_toshiba_rows_per_refresh = 646;
+                       mddi_toshiba_usecs_per_refresh = 16344;
+               } else {
+                       write_client_reg(HCYCLE, 0x0000010b, TRUE);
+                       mddi_toshiba_rows_per_second = 37313;
+                       mddi_toshiba_rows_per_refresh = 646;
+                       mddi_toshiba_usecs_per_refresh = 17313;
+               }
+
+               write_client_reg(HSW, 0x00000003, TRUE);
+               write_client_reg(HDE_START, 0x00000007, TRUE);
+               write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
+               write_client_reg(VCYCLE, 0x00000285, TRUE);
+               write_client_reg(VSW, 0x00000001, TRUE);
+               write_client_reg(VDE_START, 0x00000003, TRUE);
+               write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
+               write_client_reg(START, 0x00000001, TRUE);
+               mddi_wait(10);
+               write_client_reg(SSITX, 0x000800BC, TRUE);
+               write_client_reg(SSITX, 0x00000180, TRUE);
+               write_client_reg(SSITX, 0x0008003B, TRUE);
+               write_client_reg(SSITX, 0x00000100, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX, 0x000800B0, TRUE);
+               write_client_reg(SSITX, 0x00000116, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX, 0x000800B8, TRUE);
+               write_client_reg(SSITX, 0x000801FF, TRUE);
+               write_client_reg(SSITX, 0x000001F5, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX, 0x00000011, TRUE);
+               write_client_reg(SSITX, 0x00000029, TRUE);
+               write_client_reg(WKREQ, 0x00000000, TRUE);
+               write_client_reg(WAKEUP, 0x00000000, TRUE);
+               write_client_reg(INTMSK, 0x00000001, TRUE);
+       }
+
+       mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
+                                     TOSHIBA_STATE_PRIM_NORMAL_MODE);
+}
+
+static void toshiba_sec_start(struct msm_fb_data_type *mfd)
+{
+       if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+               return;
+
+       write_client_reg(VSYNIF, 0x00000000, TRUE);
+       write_client_reg(PORT_ENB, 0x00000002, TRUE);
+       write_client_reg(CLKENB, 0x000011EF, TRUE);
+       write_client_reg(BITMAP0, 0x028001E0, TRUE);
+       write_client_reg(BITMAP1, 0x00000000, TRUE);
+       write_client_reg(BITMAP2, 0x00000000, TRUE);
+       write_client_reg(BITMAP3, 0x00000000, TRUE);
+       write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+       write_client_reg(PORT, 0x00000000, TRUE);
+       write_client_reg(PXL, 0x00000000, TRUE);
+       write_client_reg(MPLFBUF, 0x00000004, TRUE);
+       write_client_reg(HCYCLE, 0x0000006B, TRUE);
+       write_client_reg(HSW, 0x00000003, TRUE);
+       write_client_reg(HDE_START, 0x00000007, TRUE);
+       write_client_reg(HDE_SIZE, 0x00000057, TRUE);
+       write_client_reg(VCYCLE, 0x000000E6, TRUE);
+       write_client_reg(VSW, 0x00000001, TRUE);
+       write_client_reg(VDE_START, 0x00000003, TRUE);
+       write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
+       write_client_reg(ASY_DATA, 0x80000001, TRUE);
+       write_client_reg(ASY_DATB, 0x0000011B, TRUE);
+       write_client_reg(ASY_DATC, 0x80000002, TRUE);
+       write_client_reg(ASY_DATD, 0x00000700, TRUE);
+       write_client_reg(ASY_DATE, 0x80000003, TRUE);
+       write_client_reg(ASY_DATF, 0x00000230, TRUE);
+       write_client_reg(ASY_DATG, 0x80000008, TRUE);
+       write_client_reg(ASY_DATH, 0x00000402, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+       write_client_reg(ASY_DATA, 0x80000009, TRUE);
+       write_client_reg(ASY_DATB, 0x00000000, TRUE);
+       write_client_reg(ASY_DATC, 0x8000000B, TRUE);
+       write_client_reg(ASY_DATD, 0x00000000, TRUE);
+       write_client_reg(ASY_DATE, 0x8000000C, TRUE);
+       write_client_reg(ASY_DATF, 0x00000000, TRUE);
+       write_client_reg(ASY_DATG, 0x8000000D, TRUE);
+       write_client_reg(ASY_DATH, 0x00000409, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+       write_client_reg(ASY_DATA, 0x8000000E, TRUE);
+       write_client_reg(ASY_DATB, 0x00000409, TRUE);
+       write_client_reg(ASY_DATC, 0x80000030, TRUE);
+       write_client_reg(ASY_DATD, 0x00000000, TRUE);
+       write_client_reg(ASY_DATE, 0x80000031, TRUE);
+       write_client_reg(ASY_DATF, 0x00000100, TRUE);
+       write_client_reg(ASY_DATG, 0x80000032, TRUE);
+       write_client_reg(ASY_DATH, 0x00000104, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+       write_client_reg(ASY_DATA, 0x80000033, TRUE);
+       write_client_reg(ASY_DATB, 0x00000400, TRUE);
+       write_client_reg(ASY_DATC, 0x80000034, TRUE);
+       write_client_reg(ASY_DATD, 0x00000306, TRUE);
+       write_client_reg(ASY_DATE, 0x80000035, TRUE);
+       write_client_reg(ASY_DATF, 0x00000706, TRUE);
+       write_client_reg(ASY_DATG, 0x80000036, TRUE);
+       write_client_reg(ASY_DATH, 0x00000707, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+       write_client_reg(ASY_DATA, 0x80000037, TRUE);
+       write_client_reg(ASY_DATB, 0x00000004, TRUE);
+       write_client_reg(ASY_DATC, 0x80000038, TRUE);
+       write_client_reg(ASY_DATD, 0x00000000, TRUE);
+       write_client_reg(ASY_DATE, 0x80000039, TRUE);
+       write_client_reg(ASY_DATF, 0x00000000, TRUE);
+       write_client_reg(ASY_DATG, 0x8000003A, TRUE);
+       write_client_reg(ASY_DATH, 0x00000001, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+       write_client_reg(ASY_DATA, 0x80000044, TRUE);
+       write_client_reg(ASY_DATB, 0x0000AF00, TRUE);
+       write_client_reg(ASY_DATC, 0x80000045, TRUE);
+       write_client_reg(ASY_DATD, 0x0000DB00, TRUE);
+       write_client_reg(ASY_DATE, 0x08000042, TRUE);
+       write_client_reg(ASY_DATF, 0x0000DB00, TRUE);
+       write_client_reg(ASY_DATG, 0x80000021, TRUE);
+       write_client_reg(ASY_DATH, 0x00000000, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+       write_client_reg(PXL, 0x0000000C, TRUE);
+       write_client_reg(VSYNIF, 0x00000001, TRUE);
+       write_client_reg(ASY_DATA, 0x80000022, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000003, TRUE);
+       write_client_reg(START, 0x00000001, TRUE);
+       mddi_wait(60);
+       write_client_reg(PXL, 0x00000000, TRUE);
+       write_client_reg(VSYNIF, 0x00000000, TRUE);
+       write_client_reg(START, 0x00000000, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+       write_client_reg(ASY_DATA, 0x80000050, TRUE);
+       write_client_reg(ASY_DATB, 0x00000000, TRUE);
+       write_client_reg(ASY_DATC, 0x80000051, TRUE);
+       write_client_reg(ASY_DATD, 0x00000E00, TRUE);
+       write_client_reg(ASY_DATE, 0x80000052, TRUE);
+       write_client_reg(ASY_DATF, 0x00000D01, TRUE);
+       write_client_reg(ASY_DATG, 0x80000053, TRUE);
+       write_client_reg(ASY_DATH, 0x00000000, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+       write_client_reg(ASY_DATA, 0x80000058, TRUE);
+       write_client_reg(ASY_DATB, 0x00000000, TRUE);
+       write_client_reg(ASY_DATC, 0x8000005A, TRUE);
+       write_client_reg(ASY_DATD, 0x00000E01, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+       write_client_reg(ASY_DATA, 0x80000011, TRUE);
+       write_client_reg(ASY_DATB, 0x00000812, TRUE);
+       write_client_reg(ASY_DATC, 0x80000012, TRUE);
+       write_client_reg(ASY_DATD, 0x00000003, TRUE);
+       write_client_reg(ASY_DATE, 0x80000013, TRUE);
+       write_client_reg(ASY_DATF, 0x00000909, TRUE);
+       write_client_reg(ASY_DATG, 0x80000010, TRUE);
+       write_client_reg(ASY_DATH, 0x00000040, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+       mddi_wait(40);
+       write_client_reg(ASY_DATA, 0x80000010, TRUE);
+       write_client_reg(ASY_DATB, 0x00000340, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(60);
+       write_client_reg(ASY_DATA, 0x80000010, TRUE);
+       write_client_reg(ASY_DATB, 0x00003340, TRUE);
+       write_client_reg(ASY_DATC, 0x80000007, TRUE);
+       write_client_reg(ASY_DATD, 0x00004007, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+       mddi_wait(1);
+       write_client_reg(ASY_DATA, 0x80000007, TRUE);
+       write_client_reg(ASY_DATB, 0x00004017, TRUE);
+       write_client_reg(ASY_DATC, 0x8000005B, TRUE);
+       write_client_reg(ASY_DATD, 0x00000000, TRUE);
+       write_client_reg(ASY_DATE, 0x80000059, TRUE);
+       write_client_reg(ASY_DATF, 0x00000011, TRUE);
+       write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
+       write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
+       mddi_wait(20);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       /* LTPS I/F control */
+       write_client_reg(ASY_DATB, 0x00000019, TRUE);
+       /* Direct cmd transfer enable */
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       /* Direct cmd transfer disable */
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(20);
+       /* Index setting of SUB LCDD */
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       /* LTPS I/F control */
+       write_client_reg(ASY_DATB, 0x00000079, TRUE);
+       /* Direct cmd transfer enable */
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       /* Direct cmd transfer disable */
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(20);
+       /* Index setting of SUB LCDD */
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       /* LTPS I/F control */
+       write_client_reg(ASY_DATB, 0x000003FD, TRUE);
+       /* Direct cmd transfer enable */
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       /* Direct cmd transfer disable */
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(20);
+       mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
+                                     TOSHIBA_STATE_SEC_NORMAL_MODE);
+}
+
+static void toshiba_prim_lcd_off(struct msm_fb_data_type *mfd)
+{
+       if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+               gordon_disp_off();
+       } else{
+
+               /* Main panel power off (Deep standby in) */
+               write_client_reg(SSITX, 0x000800BC, TRUE);
+               write_client_reg(SSITX, 0x00000100, TRUE);
+               write_client_reg(SSITX, 0x00000028, TRUE);
+               mddi_wait(1);
+               write_client_reg(SSITX, 0x000800B8, TRUE);
+               write_client_reg(SSITX, 0x00000180, TRUE);
+               write_client_reg(SSITX, 0x00000102, TRUE);
+               write_client_reg(SSITX, 0x00000010, TRUE);
+       }
+       write_client_reg(PORT, 0x00000003, TRUE);
+       write_client_reg(REGENB, 0x00000001, TRUE);
+       mddi_wait(1);
+       write_client_reg(PXL, 0x00000000, TRUE);
+       write_client_reg(START, 0x00000000, TRUE);
+       write_client_reg(REGENB, 0x00000001, TRUE);
+       mddi_wait(3);
+       if (TM_GET_PID(mfd->panel.id) != LCD_SHARP_2P4_VGA) {
+               write_client_reg(SSITX, 0x000800B0, TRUE);
+               write_client_reg(SSITX, 0x00000100, TRUE);
+       }
+       mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_NORMAL_MODE,
+                                     TOSHIBA_STATE_PRIM_SEC_STANDBY);
+}
+
+static void toshiba_sec_lcd_off(struct msm_fb_data_type *mfd)
+{
+       if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+               return;
+
+       write_client_reg(VSYNIF, 0x00000000, TRUE);
+       write_client_reg(PORT_ENB, 0x00000002, TRUE);
+       write_client_reg(ASY_DATA, 0x80000007, TRUE);
+       write_client_reg(ASY_DATB, 0x00004016, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       write_client_reg(ASY_DATB, 0x00000019, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       write_client_reg(ASY_DATB, 0x0000000B, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       write_client_reg(ASY_DATB, 0x00000002, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(4);
+       write_client_reg(ASY_DATA, 0x80000010, TRUE);
+       write_client_reg(ASY_DATB, 0x00000300, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(4);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       write_client_reg(ASY_DATB, 0x00000000, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(ASY_DATA, 0x80000007, TRUE);
+       write_client_reg(ASY_DATB, 0x00004004, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(PORT, 0x00000000, TRUE);
+       write_client_reg(PXL, 0x00000000, TRUE);
+       write_client_reg(START, 0x00000000, TRUE);
+       write_client_reg(VSYNIF, 0x00000001, TRUE);
+       write_client_reg(PORT_ENB, 0x00000001, TRUE);
+       write_client_reg(REGENB, 0x00000001, TRUE);
+       mddi_toshiba_state_transition(TOSHIBA_STATE_SEC_NORMAL_MODE,
+                                     TOSHIBA_STATE_PRIM_SEC_STANDBY);
+}
+
+static void toshiba_sec_cont_update_start(struct msm_fb_data_type *mfd)
+{
+
+       if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+               return;
+
+       write_client_reg(VSYNIF, 0x00000000, TRUE);
+       write_client_reg(PORT_ENB, 0x00000002, TRUE);
+       write_client_reg(INTMASK, 0x00000001, TRUE);
+       write_client_reg(TTBUSSEL, 0x0000000B, TRUE);
+       write_client_reg(MONI, 0x00000008, TRUE);
+       write_client_reg(CLKENB, 0x000000EF, TRUE);
+       write_client_reg(CLKENB, 0x000010EF, TRUE);
+       write_client_reg(CLKENB, 0x000011EF, TRUE);
+       write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+       write_client_reg(HCYCLE, 0x0000006B, TRUE);
+       write_client_reg(HSW, 0x00000003, TRUE);
+       write_client_reg(HDE_START, 0x00000002, TRUE);
+       write_client_reg(HDE_SIZE, 0x00000057, TRUE);
+       write_client_reg(VCYCLE, 0x000000E6, TRUE);
+       write_client_reg(VSW, 0x00000001, TRUE);
+       write_client_reg(VDE_START, 0x00000003, TRUE);
+       write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
+       write_client_reg(WRSTB, 0x00000015, TRUE);
+       write_client_reg(MPLFBUF, 0x00000004, TRUE);
+       write_client_reg(ASY_DATA, 0x80000021, TRUE);
+       write_client_reg(ASY_DATB, 0x00000000, TRUE);
+       write_client_reg(ASY_DATC, 0x80000022, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000007, TRUE);
+       write_client_reg(PXL, 0x00000089, TRUE);
+       write_client_reg(VSYNIF, 0x00000001, TRUE);
+       mddi_wait(2);
+}
+
+static void toshiba_sec_cont_update_stop(struct msm_fb_data_type *mfd)
+{
+       if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+               return;
+
+       write_client_reg(PXL, 0x00000000, TRUE);
+       write_client_reg(VSYNIF, 0x00000000, TRUE);
+       write_client_reg(START, 0x00000000, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+       mddi_wait(3);
+       write_client_reg(SRST, 0x00000002, TRUE);
+       mddi_wait(3);
+       write_client_reg(SRST, 0x00000003, TRUE);
+}
+
+static void toshiba_sec_backlight_on(struct msm_fb_data_type *mfd)
+{
+       if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+               return;
+
+       write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+       write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+       write_client_reg(PWM0OFF, 0x00000001, TRUE);
+       write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+       write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+       write_client_reg(PWM1OFF, 0x00001387, TRUE);
+       write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+       write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+       write_client_reg(PWMCR, 0x00000003, TRUE);
+}
+
+static void toshiba_sec_sleep_in(struct msm_fb_data_type *mfd)
+{
+       if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+               return;
+
+       write_client_reg(VSYNIF, 0x00000000, TRUE);
+       write_client_reg(PORT_ENB, 0x00000002, TRUE);
+       write_client_reg(ASY_DATA, 0x80000007, TRUE);
+       write_client_reg(ASY_DATB, 0x00004016, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       write_client_reg(ASY_DATB, 0x00000019, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       write_client_reg(ASY_DATB, 0x0000000B, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       write_client_reg(ASY_DATB, 0x00000002, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(4);
+       write_client_reg(ASY_DATA, 0x80000010, TRUE);
+       write_client_reg(ASY_DATB, 0x00000300, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(4);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       write_client_reg(ASY_DATB, 0x00000000, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(ASY_DATA, 0x80000007, TRUE);
+       write_client_reg(ASY_DATB, 0x00004004, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(PORT, 0x00000000, TRUE);
+       write_client_reg(PXL, 0x00000000, TRUE);
+       write_client_reg(START, 0x00000000, TRUE);
+       write_client_reg(REGENB, 0x00000001, TRUE);
+       /* Sleep in sequence */
+       write_client_reg(ASY_DATA, 0x80000010, TRUE);
+       write_client_reg(ASY_DATB, 0x00000302, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+}
+
+static void toshiba_sec_sleep_out(struct msm_fb_data_type *mfd)
+{
+       if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+               return;
+
+       write_client_reg(VSYNIF, 0x00000000, TRUE);
+       write_client_reg(PORT_ENB, 0x00000002, TRUE);
+       write_client_reg(ASY_DATA, 0x80000010, TRUE);
+       write_client_reg(ASY_DATB, 0x00000300, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       /*  Display ON sequence */
+       write_client_reg(ASY_DATA, 0x80000011, TRUE);
+       write_client_reg(ASY_DATB, 0x00000812, TRUE);
+       write_client_reg(ASY_DATC, 0x80000012, TRUE);
+       write_client_reg(ASY_DATD, 0x00000003, TRUE);
+       write_client_reg(ASY_DATE, 0x80000013, TRUE);
+       write_client_reg(ASY_DATF, 0x00000909, TRUE);
+       write_client_reg(ASY_DATG, 0x80000010, TRUE);
+       write_client_reg(ASY_DATH, 0x00000040, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+       mddi_wait(4);
+       write_client_reg(ASY_DATA, 0x80000010, TRUE);
+       write_client_reg(ASY_DATB, 0x00000340, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(6);
+       write_client_reg(ASY_DATA, 0x80000010, TRUE);
+       write_client_reg(ASY_DATB, 0x00003340, TRUE);
+       write_client_reg(ASY_DATC, 0x80000007, TRUE);
+       write_client_reg(ASY_DATD, 0x00004007, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+       mddi_wait(1);
+       write_client_reg(ASY_DATA, 0x80000007, TRUE);
+       write_client_reg(ASY_DATB, 0x00004017, TRUE);
+       write_client_reg(ASY_DATC, 0x8000005B, TRUE);
+       write_client_reg(ASY_DATD, 0x00000000, TRUE);
+       write_client_reg(ASY_DATE, 0x80000059, TRUE);
+       write_client_reg(ASY_DATF, 0x00000011, TRUE);
+       write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
+       write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
+       mddi_wait(2);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       write_client_reg(ASY_DATB, 0x00000019, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       write_client_reg(ASY_DATB, 0x00000079, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+       write_client_reg(ASY_DATA, 0x80000059, TRUE);
+       write_client_reg(ASY_DATB, 0x000003FD, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+       write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+       mddi_wait(2);
+}
+
+static void mddi_toshiba_lcd_set_backlight(struct msm_fb_data_type *mfd)
+{
+       int32 level;
+       int ret = -EPERM;
+       int max = mfd->panel_info.bl_max;
+       int min = mfd->panel_info.bl_min;
+
+       if (mddi_toshiba_pdata && mddi_toshiba_pdata->pmic_backlight) {
+               ret = mddi_toshiba_pdata->pmic_backlight(mfd->bl_level);
+               if (!ret)
+                       return;
+       }
+
+       if (ret && mddi_toshiba_pdata && mddi_toshiba_pdata->backlight_level) {
+               level = mddi_toshiba_pdata->backlight_level(mfd->bl_level,
+                                                               max, min);
+
+               if (level < 0)
+                       return;
+
+               if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
+                       write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+       } else {
+               if (!max)
+                       level = 0;
+               else
+                       level = (mfd->bl_level * 4999) / max;
+       }
+
+       write_client_reg(PWM0OFF, level, TRUE);
+}
+
+static void mddi_toshiba_vsync_set_handler(msm_fb_vsync_handler_type handler,  /* ISR to be executed */
+                                          void *arg)
+{
+       boolean error = FALSE;
+       unsigned long flags;
+
+       /* Disable interrupts */
+       spin_lock_irqsave(&mddi_host_spin_lock, flags);
+       /* INTLOCK(); */
+
+       if (mddi_toshiba_vsync_handler != NULL) {
+               error = TRUE;
+       } else {
+               /* Register the handler for this particular GROUP interrupt source */
+               mddi_toshiba_vsync_handler = handler;
+               mddi_toshiba_vsync_handler_arg = arg;
+       }
+
+       /* Restore interrupts */
+       spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+       /* MDDI_INTFREE(); */
+       if (error) {
+               MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
+       } else {
+               /* Enable the vsync wakeup */
+               mddi_queue_register_write(INTMSK, 0x0000, FALSE, 0);
+
+               mddi_toshiba_vsync_attempts = 1;
+               mddi_vsync_detect_enabled = TRUE;
+       }
+}                              /* mddi_toshiba_vsync_set_handler */
+
+static void mddi_toshiba_lcd_vsync_detected(boolean detected)
+{
+       /* static timetick_type start_time = 0; */
+       static struct timeval start_time;
+       static boolean first_time = TRUE;
+       /* uint32 mdp_cnt_val = 0; */
+       /* timetick_type elapsed_us; */
+       struct timeval now;
+       uint32 elapsed_us;
+       uint32 num_vsyncs;
+
+       if ((detected) || (mddi_toshiba_vsync_attempts > 5)) {
+               if ((detected) && (mddi_toshiba_monitor_refresh_value)) {
+                       /* if (start_time != 0) */
+                       if (!first_time) {
+                               jiffies_to_timeval(jiffies, &now);
+                               elapsed_us =
+                                   (now.tv_sec - start_time.tv_sec) * 1000000 +
+                                   now.tv_usec - start_time.tv_usec;
+                               /*
+                                * LCD is configured for a refresh every usecs,
+                                *  so to determine the number of vsyncs that
+                                *  have occurred since the last measurement
+                                *  add half that to the time difference and
+                                *  divide by the refresh rate.
+                                */
+                               num_vsyncs = (elapsed_us +
+                                             (mddi_toshiba_usecs_per_refresh >>
+                                              1)) /
+                                   mddi_toshiba_usecs_per_refresh;
+                               /*
+                                * LCD is configured for * hsyncs (rows) per
+                                * refresh cycle. Calculate new rows_per_second
+                                * value based upon these new measurements.
+                                * MDP can update with this new value.
+                                */
+                               mddi_toshiba_rows_per_second =
+                                   (mddi_toshiba_rows_per_refresh * 1000 *
+                                    num_vsyncs) / (elapsed_us / 1000);
+                       }
+                       /* start_time = timetick_get(); */
+                       first_time = FALSE;
+                       jiffies_to_timeval(jiffies, &start_time);
+                       if (mddi_toshiba_report_refresh_measurements) {
+                               (void)mddi_queue_register_read_int(VPOS,
+                                                                  &mddi_toshiba_curr_vpos);
+                               /* mdp_cnt_val = MDP_LINE_COUNT; */
+                       }
+               }
+               /* if detected = TRUE, client initiated wakeup was detected */
+               if (mddi_toshiba_vsync_handler != NULL) {
+                       (*mddi_toshiba_vsync_handler)
+                           (mddi_toshiba_vsync_handler_arg);
+                       mddi_toshiba_vsync_handler = NULL;
+               }
+               mddi_vsync_detect_enabled = FALSE;
+               mddi_toshiba_vsync_attempts = 0;
+               /* need to disable the interrupt wakeup */
+               if (!mddi_queue_register_write_int(INTMSK, 0x0001))
+                       MDDI_MSG_ERR("Vsync interrupt disable failed!\n");
+               if (!detected) {
+                       /* give up after 5 failed attempts but show error */
+                       MDDI_MSG_NOTICE("Vsync detection failed!\n");
+               } else if ((mddi_toshiba_monitor_refresh_value) &&
+                          (mddi_toshiba_report_refresh_measurements)) {
+                       MDDI_MSG_NOTICE("  Last Line Counter=%d!\n",
+                                       mddi_toshiba_curr_vpos);
+               /* MDDI_MSG_NOTICE("  MDP Line Counter=%d!\n",mdp_cnt_val); */
+                       MDDI_MSG_NOTICE("  Lines Per Second=%d!\n",
+                                       mddi_toshiba_rows_per_second);
+               }
+               /* clear the interrupt */
+               if (!mddi_queue_register_write_int(INTFLG, 0x0001))
+                       MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
+       } else {
+               /* if detected = FALSE, we woke up from hibernation, but did not
+                * detect client initiated wakeup.
+                */
+               mddi_toshiba_vsync_attempts++;
+       }
+}
+
+static void mddi_toshiba_prim_init(struct msm_fb_data_type *mfd)
+{
+
+       switch (toshiba_state) {
+       case TOSHIBA_STATE_PRIM_SEC_READY:
+               break;
+       case TOSHIBA_STATE_OFF:
+               toshiba_state = TOSHIBA_STATE_PRIM_SEC_STANDBY;
+               toshiba_common_initial_setup(mfd);
+               break;
+       case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+               toshiba_common_initial_setup(mfd);
+               break;
+       case TOSHIBA_STATE_SEC_NORMAL_MODE:
+               toshiba_sec_cont_update_stop(mfd);
+               toshiba_sec_sleep_in(mfd);
+               toshiba_sec_sleep_out(mfd);
+               toshiba_sec_lcd_off(mfd);
+               toshiba_common_initial_setup(mfd);
+               break;
+       default:
+               MDDI_MSG_ERR("mddi_toshiba_prim_init from state %d\n",
+                            toshiba_state);
+       }
+
+       toshiba_prim_start(mfd);
+       if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
+               gordon_disp_init();
+       mddi_host_write_pix_attr_reg(0x00C3);
+}
+
+static void mddi_toshiba_sec_init(struct msm_fb_data_type *mfd)
+{
+
+       switch (toshiba_state) {
+       case TOSHIBA_STATE_PRIM_SEC_READY:
+               break;
+       case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+               toshiba_common_initial_setup(mfd);
+               break;
+       case TOSHIBA_STATE_PRIM_NORMAL_MODE:
+               toshiba_prim_lcd_off(mfd);
+               toshiba_common_initial_setup(mfd);
+               break;
+       default:
+               MDDI_MSG_ERR("mddi_toshiba_sec_init from state %d\n",
+                            toshiba_state);
+       }
+
+       toshiba_sec_start(mfd);
+       toshiba_sec_backlight_on(mfd);
+       toshiba_sec_cont_update_start(mfd);
+       mddi_host_write_pix_attr_reg(0x0400);
+}
+
+static void mddi_toshiba_lcd_powerdown(struct msm_fb_data_type *mfd)
+{
+       switch (toshiba_state) {
+       case TOSHIBA_STATE_PRIM_SEC_READY:
+               mddi_toshiba_prim_init(mfd);
+               mddi_toshiba_lcd_powerdown(mfd);
+               return;
+       case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+               break;
+       case TOSHIBA_STATE_PRIM_NORMAL_MODE:
+               toshiba_prim_lcd_off(mfd);
+               break;
+       case TOSHIBA_STATE_SEC_NORMAL_MODE:
+               toshiba_sec_cont_update_stop(mfd);
+               toshiba_sec_sleep_in(mfd);
+               toshiba_sec_sleep_out(mfd);
+               toshiba_sec_lcd_off(mfd);
+               break;
+       default:
+               MDDI_MSG_ERR("mddi_toshiba_lcd_powerdown from state %d\n",
+                            toshiba_state);
+       }
+}
+
+static int mddi_sharpgordon_firsttime = 1;
+
+static int mddi_toshiba_lcd_on(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+       mfd = platform_get_drvdata(pdev);
+       if (!mfd)
+               return -ENODEV;
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       if (TM_GET_DID(mfd->panel.id) == TOSHIBA_VGA_PRIM)
+               mddi_toshiba_prim_init(mfd);
+       else
+               mddi_toshiba_sec_init(mfd);
+       if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+               if (mddi_sharpgordon_firsttime) {
+                       mddi_sharpgordon_firsttime = 0;
+                       write_client_reg(REGENB, 0x00000001, TRUE);
+               }
+       }
+       return 0;
+}
+
+static int mddi_toshiba_lcd_off(struct platform_device *pdev)
+{
+       mddi_toshiba_lcd_powerdown(platform_get_drvdata(pdev));
+       return 0;
+}
+
+static int __init mddi_toshiba_lcd_probe(struct platform_device *pdev)
+{
+       if (pdev->id == 0) {
+               mddi_toshiba_pdata = pdev->dev.platform_data;
+               return 0;
+       }
+
+       msm_fb_add_device(pdev);
+
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = mddi_toshiba_lcd_probe,
+       .driver = {
+               .name   = "mddi_toshiba",
+       },
+};
+
+static struct msm_fb_panel_data toshiba_panel_data = {
+       .on             = mddi_toshiba_lcd_on,
+       .off            = mddi_toshiba_lcd_off,
+};
+
+static int ch_used[3];
+
+int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
+                                       u32 channel, u32 panel)
+{
+       struct platform_device *pdev = NULL;
+       int ret;
+
+       if ((channel >= 3) || ch_used[channel])
+               return -ENODEV;
+
+       if ((channel != TOSHIBA_VGA_PRIM) &&
+           mddi_toshiba_pdata && mddi_toshiba_pdata->panel_num)
+               if (mddi_toshiba_pdata->panel_num() < 2)
+                       return -ENODEV;
+
+       ch_used[channel] = TRUE;
+
+       pdev = platform_device_alloc("mddi_toshiba", (panel << 8)|channel);
+       if (!pdev)
+               return -ENOMEM;
+
+       if (channel == TOSHIBA_VGA_PRIM) {
+               toshiba_panel_data.set_backlight =
+                               mddi_toshiba_lcd_set_backlight;
+
+               if (pinfo->lcd.vsync_enable) {
+                       toshiba_panel_data.set_vsync_notifier =
+                               mddi_toshiba_vsync_set_handler;
+                       mddi_lcd.vsync_detected =
+                               mddi_toshiba_lcd_vsync_detected;
+               }
+       } else {
+               toshiba_panel_data.set_backlight = NULL;
+               toshiba_panel_data.set_vsync_notifier = NULL;
+       }
+
+       toshiba_panel_data.panel_info = *pinfo;
+
+       ret = platform_device_add_data(pdev, &toshiba_panel_data,
+               sizeof(toshiba_panel_data));
+       if (ret) {
+               printk(KERN_ERR
+                 "%s: platform_device_add_data failed!\n", __func__);
+               goto err_device_put;
+       }
+
+       ret = platform_device_add(pdev);
+       if (ret) {
+               printk(KERN_ERR
+                 "%s: platform_device_register failed!\n", __func__);
+               goto err_device_put;
+       }
+
+       return 0;
+
+err_device_put:
+       platform_device_put(pdev);
+       return ret;
+}
+
+static int __init mddi_toshiba_lcd_init(void)
+{
+       return platform_driver_register(&this_driver);
+}
+
+module_init(mddi_toshiba_lcd_init);
diff --git a/drivers/staging/msm/mddi_toshiba.h b/drivers/staging/msm/mddi_toshiba.h
new file mode 100644 (file)
index 0000000..2d22b9a
--- /dev/null
@@ -0,0 +1,52 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDDI_TOSHIBA_H
+#define MDDI_TOSHIBA_H
+
+#define TOSHIBA_VGA_PRIM 1
+#define TOSHIBA_VGA_SECD 2
+
+#define LCD_TOSHIBA_2P4_VGA    0
+#define LCD_TOSHIBA_2P4_WVGA   1
+#define LCD_TOSHIBA_2P4_WVGA_PT        2
+#define LCD_SHARP_2P4_VGA      3
+
+#define GPIO_BLOCK_BASE        0x150000
+#define SYSTEM_BLOCK2_BASE     0x170000
+
+#define GPIODIR     (GPIO_BLOCK_BASE|0x04)
+#define GPIOSEL     (SYSTEM_BLOCK2_BASE|0x00)
+#define GPIOPC      (GPIO_BLOCK_BASE|0x28)
+#define GPIODATA    (GPIO_BLOCK_BASE|0x00)
+
+#define write_client_reg(__X, __Y, __Z) {\
+  mddi_queue_register_write(__X, __Y, TRUE, 0);\
+}
+
+#endif /* MDDI_TOSHIBA_H */
diff --git a/drivers/staging/msm/mddi_toshiba_vga.c b/drivers/staging/msm/mddi_toshiba_vga.c
new file mode 100644 (file)
index 0000000..7e61d3a
--- /dev/null
@@ -0,0 +1,136 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+static uint32 read_client_reg(uint32 addr)
+{
+       uint32 val;
+       mddi_queue_register_read(addr, &val, TRUE, 0);
+       return val;
+}
+
+static uint32 toshiba_lcd_gpio_read(void)
+{
+       uint32 val;
+
+       write_client_reg(GPIODIR, 0x0000000C, TRUE);
+       write_client_reg(GPIOSEL, 0x00000000, TRUE);
+       write_client_reg(GPIOSEL, 0x00000000, TRUE);
+       write_client_reg(GPIOPC, 0x03CF00C0, TRUE);
+       val = read_client_reg(GPIODATA) & 0x2C0;
+
+       return val;
+}
+
+static u32 mddi_toshiba_panel_detect(void)
+{
+       mddi_host_type host_idx = MDDI_HOST_PRIM;
+       uint32 lcd_gpio;
+       u32 mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
+
+       /* Toshiba display requires larger drive_lo value */
+       mddi_host_reg_out(DRIVE_LO, 0x0050);
+
+       lcd_gpio = toshiba_lcd_gpio_read();
+       switch (lcd_gpio) {
+       case 0x0080:
+               mddi_toshiba_lcd = LCD_SHARP_2P4_VGA;
+               break;
+
+       case 0x00C0:
+       default:
+               mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
+               break;
+       }
+
+       return mddi_toshiba_lcd;
+}
+
+static int __init mddi_toshiba_vga_init(void)
+{
+       int ret;
+       struct msm_panel_info pinfo;
+       u32 panel;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+       u32 id;
+
+       ret = msm_fb_detect_client("mddi_toshiba_vga");
+       if (ret == -ENODEV)
+               return 0;
+
+       if (ret) {
+               id = mddi_get_client_id();
+               if ((id >> 16) != 0xD263)
+                       return 0;
+       }
+#endif
+
+       panel = mddi_toshiba_panel_detect();
+
+       pinfo.xres = 480;
+       pinfo.yres = 640;
+       pinfo.type = MDDI_PANEL;
+       pinfo.pdest = DISPLAY_1;
+       pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+       pinfo.wait_cycle = 0;
+       pinfo.bpp = 18;
+       pinfo.lcd.vsync_enable = TRUE;
+       pinfo.lcd.refx100 = 6118;
+       pinfo.lcd.v_back_porch = 6;
+       pinfo.lcd.v_front_porch = 0;
+       pinfo.lcd.v_pulse_width = 0;
+       pinfo.lcd.hw_vsync_mode = FALSE;
+       pinfo.lcd.vsync_notifier_period = (1 * HZ);
+       pinfo.bl_max = 99;
+       pinfo.bl_min = 1;
+       pinfo.clk_rate = 122880000;
+       pinfo.clk_min =  120000000;
+       pinfo.clk_max =  200000000;
+       pinfo.fb_num = 2;
+
+       ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, panel);
+       if (ret) {
+               printk(KERN_ERR "%s: failed to register device!\n", __func__);
+               return ret;
+       }
+
+       pinfo.xres = 176;
+       pinfo.yres = 220;
+       pinfo.type = MDDI_PANEL;
+       pinfo.pdest = DISPLAY_2;
+       pinfo.mddi.vdopkt = 0x400;
+       pinfo.wait_cycle = 0;
+       pinfo.bpp = 18;
+       pinfo.clk_rate = 122880000;
+       pinfo.clk_min =  120000000;
+       pinfo.clk_max =  200000000;
+       pinfo.fb_num = 2;
+
+       ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_SECD, panel);
+       if (ret)
+               printk(KERN_WARNING
+                       "%s: failed to register device!\n", __func__);
+
+       return ret;
+}
+
+module_init(mddi_toshiba_vga_init);
diff --git a/drivers/staging/msm/mddi_toshiba_wvga.c b/drivers/staging/msm/mddi_toshiba_wvga.c
new file mode 100644 (file)
index 0000000..557b0f0
--- /dev/null
@@ -0,0 +1,63 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddi_toshiba.h"
+
+static int __init mddi_toshiba_wvga_init(void)
+{
+       int ret;
+       struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+       if (msm_fb_detect_client("mddi_toshiba_wvga"))
+               return 0;
+#endif
+
+       pinfo.xres = 800;
+       pinfo.yres = 480;
+       pinfo.pdest = DISPLAY_2;
+       pinfo.type = MDDI_PANEL;
+       pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+       pinfo.wait_cycle = 0;
+       pinfo.bpp = 18;
+       pinfo.lcd.vsync_enable = TRUE;
+       pinfo.lcd.refx100 = 6118;
+       pinfo.lcd.v_back_porch = 6;
+       pinfo.lcd.v_front_porch = 0;
+       pinfo.lcd.v_pulse_width = 0;
+       pinfo.lcd.hw_vsync_mode = FALSE;
+       pinfo.lcd.vsync_notifier_period = (1 * HZ);
+       pinfo.bl_max = 4;
+       pinfo.bl_min = 1;
+       pinfo.clk_rate = 192000000;
+       pinfo.clk_min =  190000000;
+       pinfo.clk_max =  200000000;
+       pinfo.fb_num = 2;
+
+       ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM,
+                                          LCD_TOSHIBA_2P4_WVGA);
+       if (ret) {
+               printk(KERN_ERR "%s: failed to register device!\n", __func__);
+               return ret;
+       }
+
+       return ret;
+}
+
+module_init(mddi_toshiba_wvga_init);
diff --git a/drivers/staging/msm/mddi_toshiba_wvga_pt.c b/drivers/staging/msm/mddi_toshiba_wvga_pt.c
new file mode 100644 (file)
index 0000000..fc7d4e0
--- /dev/null
@@ -0,0 +1,64 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+static int __init mddi_toshiba_wvga_pt_init(void)
+{
+       int ret;
+       struct msm_panel_info pinfo;
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+       uint id;
+
+       ret = msm_fb_detect_client("mddi_toshiba_wvga_pt");
+       if (ret == -ENODEV)
+               return 0;
+
+       if (ret) {
+               id = mddi_get_client_id();
+               if (id != 0xd2638722)
+                       return 0;
+       }
+#endif
+
+       pinfo.xres = 480;
+       pinfo.yres = 800;
+       pinfo.type = MDDI_PANEL;
+       pinfo.pdest = DISPLAY_1;
+       pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+       pinfo.wait_cycle = 0;
+       pinfo.bpp = 18;
+       pinfo.lcd.vsync_enable = FALSE;
+       pinfo.bl_max = 15;
+       pinfo.bl_min = 1;
+       pinfo.clk_rate = 192000000;
+       pinfo.clk_min =  190000000;
+       pinfo.clk_max =  200000000;
+       pinfo.fb_num = 2;
+
+       ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM,
+                                               LCD_TOSHIBA_2P4_WVGA_PT);
+       if (ret)
+               printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+       return ret;
+}
+
+module_init(mddi_toshiba_wvga_pt_init);
diff --git a/drivers/staging/msm/mddihost.c b/drivers/staging/msm/mddihost.c
new file mode 100644 (file)
index 0000000..c6c1ee4
--- /dev/null
@@ -0,0 +1,377 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#include <linux/clk.h>
+#include <mach/clk.h>
+
+struct semaphore mddi_host_mutex;
+
+struct clk *mddi_io_clk;
+static boolean mddi_host_powered = FALSE;
+static boolean mddi_host_initialized = FALSE;
+extern uint32 *mddi_reg_read_value_ptr;
+
+mddi_lcd_func_type mddi_lcd;
+
+extern mddi_client_capability_type mddi_client_capability_pkt;
+
+#ifdef FEATURE_MDDI_HITACHI
+extern void mddi_hitachi_window_adjust(uint16 x1,
+                                      uint16 x2, uint16 y1, uint16 y2);
+#endif
+
+extern void mddi_toshiba_lcd_init(void);
+
+#ifdef FEATURE_MDDI_S6D0142
+extern void mddi_s6d0142_lcd_init(void);
+extern void mddi_s6d0142_window_adjust(uint16 x1,
+                                      uint16 x2,
+                                      uint16 y1,
+                                      uint16 y2,
+                                      mddi_llist_done_cb_type done_cb);
+#endif
+
+void mddi_init(void)
+{
+       if (mddi_host_initialized)
+               return;
+
+       mddi_host_initialized = TRUE;
+
+       init_MUTEX(&mddi_host_mutex);
+
+       if (!mddi_host_powered) {
+               down(&mddi_host_mutex);
+               mddi_host_init(MDDI_HOST_PRIM);
+               mddi_host_powered = TRUE;
+               up(&mddi_host_mutex);
+               mdelay(10);
+       }
+}
+
+int mddi_host_register_read(uint32 reg_addr,
+     uint32 *reg_value_ptr, boolean wait, mddi_host_type host) {
+       mddi_linked_list_type *curr_llist_ptr;
+       mddi_register_access_packet_type *regacc_pkt_ptr;
+       uint16 curr_llist_idx;
+       int ret = 0;
+
+       if (in_interrupt())
+               MDDI_MSG_CRIT("Called from ISR context\n");
+
+       if (!mddi_host_powered) {
+               MDDI_MSG_ERR("MDDI powered down!\n");
+               mddi_init();
+       }
+
+       down(&mddi_host_mutex);
+
+       mddi_reg_read_value_ptr = reg_value_ptr;
+       curr_llist_idx = mddi_get_reg_read_llist_item(host, TRUE);
+       if (curr_llist_idx == UNASSIGNED_INDEX) {
+               up(&mddi_host_mutex);
+
+               /* need to change this to some sort of wait */
+               MDDI_MSG_ERR("Attempting to queue up more than 1 reg read\n");
+               return -EINVAL;
+       }
+
+       curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+       curr_llist_ptr->link_controller_flags = 0x11;
+       curr_llist_ptr->packet_header_count = 14;
+       curr_llist_ptr->packet_data_count = 0;
+
+       curr_llist_ptr->next_packet_pointer = NULL;
+       curr_llist_ptr->packet_data_pointer = NULL;
+       curr_llist_ptr->reserved = 0;
+
+       regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+       regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
+       regacc_pkt_ptr->packet_type = 146;      /* register access packet */
+       regacc_pkt_ptr->bClient_ID = 0;
+       regacc_pkt_ptr->read_write_info = 0x8001;
+       regacc_pkt_ptr->register_address = reg_addr;
+
+       /* now adjust pointers */
+       mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
+                                  NULL, host);
+       /* need to check if we can write the pointer or not */
+
+       up(&mddi_host_mutex);
+
+       if (wait) {
+               int wait_ret;
+
+               mddi_linked_list_notify_type *llist_notify_ptr;
+               llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
+               wait_ret = wait_for_completion_timeout(
+                                       &(llist_notify_ptr->done_comp), 5 * HZ);
+
+               if (wait_ret <= 0)
+                       ret = -EBUSY;
+
+               if (wait_ret < 0)
+                       printk(KERN_ERR "%s: failed to wait for completion!\n",
+                               __func__);
+               else if (!wait_ret)
+                       printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
+       }
+
+       MDDI_MSG_DEBUG("Reg Read value=0x%x\n", *reg_value_ptr);
+
+       return ret;
+}                              /* mddi_host_register_read */
+
+int mddi_host_register_write(uint32 reg_addr,
+     uint32 reg_val, enum mddi_data_packet_size_type packet_size,
+     boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
+       mddi_linked_list_type *curr_llist_ptr;
+       mddi_linked_list_type *curr_llist_dma_ptr;
+       mddi_register_access_packet_type *regacc_pkt_ptr;
+       uint16 curr_llist_idx;
+       int ret = 0;
+
+       if (in_interrupt())
+               MDDI_MSG_CRIT("Called from ISR context\n");
+
+       if (!mddi_host_powered) {
+               MDDI_MSG_ERR("MDDI powered down!\n");
+               mddi_init();
+       }
+
+       down(&mddi_host_mutex);
+
+       curr_llist_idx = mddi_get_next_free_llist_item(host, TRUE);
+       curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+       curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
+
+       curr_llist_ptr->link_controller_flags = 1;
+       curr_llist_ptr->packet_header_count = 14;
+       curr_llist_ptr->packet_data_count = 4;
+
+       curr_llist_ptr->next_packet_pointer = NULL;
+       curr_llist_ptr->reserved = 0;
+
+       regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+       regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count +
+                                       (uint16)packet_size;
+       regacc_pkt_ptr->packet_type = 146;      /* register access packet */
+       regacc_pkt_ptr->bClient_ID = 0;
+       regacc_pkt_ptr->read_write_info = 0x0001;
+       regacc_pkt_ptr->register_address = reg_addr;
+       regacc_pkt_ptr->register_data_list = reg_val;
+
+       MDDI_MSG_DEBUG("Reg Access write reg=0x%x, value=0x%x\n",
+                      regacc_pkt_ptr->register_address,
+                      regacc_pkt_ptr->register_data_list);
+
+       regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
+       curr_llist_ptr->packet_data_pointer =
+           (void *)(&regacc_pkt_ptr->register_data_list);
+
+       /* now adjust pointers */
+       mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
+                                  done_cb, host);
+
+       up(&mddi_host_mutex);
+
+       if (wait) {
+               int wait_ret;
+
+               mddi_linked_list_notify_type *llist_notify_ptr;
+               llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
+               wait_ret = wait_for_completion_timeout(
+                                       &(llist_notify_ptr->done_comp), 5 * HZ);
+
+               if (wait_ret <= 0)
+                       ret = -EBUSY;
+
+               if (wait_ret < 0)
+                       printk(KERN_ERR "%s: failed to wait for completion!\n",
+                               __func__);
+               else if (!wait_ret)
+                       printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
+       }
+
+       return ret;
+}                              /* mddi_host_register_write */
+
+boolean mddi_host_register_read_int
+    (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host) {
+       mddi_linked_list_type *curr_llist_ptr;
+       mddi_register_access_packet_type *regacc_pkt_ptr;
+       uint16 curr_llist_idx;
+
+       if (!in_interrupt())
+               MDDI_MSG_CRIT("Called from TASK context\n");
+
+       if (!mddi_host_powered) {
+               MDDI_MSG_ERR("MDDI powered down!\n");
+               return FALSE;
+       }
+
+       if (down_trylock(&mddi_host_mutex) != 0)
+               return FALSE;
+
+       mddi_reg_read_value_ptr = reg_value_ptr;
+       curr_llist_idx = mddi_get_reg_read_llist_item(host, FALSE);
+       if (curr_llist_idx == UNASSIGNED_INDEX) {
+               up(&mddi_host_mutex);
+               return FALSE;
+       }
+
+       curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+       curr_llist_ptr->link_controller_flags = 0x11;
+       curr_llist_ptr->packet_header_count = 14;
+       curr_llist_ptr->packet_data_count = 0;
+
+       curr_llist_ptr->next_packet_pointer = NULL;
+       curr_llist_ptr->packet_data_pointer = NULL;
+       curr_llist_ptr->reserved = 0;
+
+       regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+       regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
+       regacc_pkt_ptr->packet_type = 146;      /* register access packet */
+       regacc_pkt_ptr->bClient_ID = 0;
+       regacc_pkt_ptr->read_write_info = 0x8001;
+       regacc_pkt_ptr->register_address = reg_addr;
+
+       /* now adjust pointers */
+       mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
+                                  NULL, host);
+       /* need to check if we can write the pointer or not */
+
+       up(&mddi_host_mutex);
+
+       return TRUE;
+
+}                              /* mddi_host_register_read */
+
+boolean mddi_host_register_write_int
+    (uint32 reg_addr,
+     uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
+       mddi_linked_list_type *curr_llist_ptr;
+       mddi_linked_list_type *curr_llist_dma_ptr;
+       mddi_register_access_packet_type *regacc_pkt_ptr;
+       uint16 curr_llist_idx;
+
+       if (!in_interrupt())
+               MDDI_MSG_CRIT("Called from TASK context\n");
+
+       if (!mddi_host_powered) {
+               MDDI_MSG_ERR("MDDI powered down!\n");
+               return FALSE;
+       }
+
+       if (down_trylock(&mddi_host_mutex) != 0)
+               return FALSE;
+
+       curr_llist_idx = mddi_get_next_free_llist_item(host, FALSE);
+       if (curr_llist_idx == UNASSIGNED_INDEX) {
+               up(&mddi_host_mutex);
+               return FALSE;
+       }
+
+       curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+       curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
+
+       curr_llist_ptr->link_controller_flags = 1;
+       curr_llist_ptr->packet_header_count = 14;
+       curr_llist_ptr->packet_data_count = 4;
+
+       curr_llist_ptr->next_packet_pointer = NULL;
+       curr_llist_ptr->reserved = 0;
+
+       regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+       regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count + 4;
+       regacc_pkt_ptr->packet_type = 146;      /* register access packet */
+       regacc_pkt_ptr->bClient_ID = 0;
+       regacc_pkt_ptr->read_write_info = 0x0001;
+       regacc_pkt_ptr->register_address = reg_addr;
+       regacc_pkt_ptr->register_data_list = reg_val;
+
+       regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
+       curr_llist_ptr->packet_data_pointer =
+           (void *)(&(regacc_pkt_ptr->register_data_list));
+
+       /* now adjust pointers */
+       mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
+                                  done_cb, host);
+       up(&mddi_host_mutex);
+
+       return TRUE;
+
+}                              /* mddi_host_register_write */
+
+void mddi_wait(uint16 time_ms)
+{
+       mdelay(time_ms);
+}
+
+void mddi_client_lcd_vsync_detected(boolean detected)
+{
+       if (mddi_lcd.vsync_detected)
+               (*mddi_lcd.vsync_detected) (detected);
+}
+
+/* extended version of function includes done callback */
+void mddi_window_adjust_ext(struct msm_fb_data_type *mfd,
+                           uint16 x1,
+                           uint16 x2,
+                           uint16 y1,
+                           uint16 y2, mddi_llist_done_cb_type done_cb)
+{
+#ifdef FEATURE_MDDI_HITACHI
+       if (mfd->panel.id == HITACHI)
+               mddi_hitachi_window_adjust(x1, x2, y1, y2);
+#elif defined(FEATURE_MDDI_S6D0142)
+       if (mfd->panel.id == MDDI_LCD_S6D0142)
+               mddi_s6d0142_window_adjust(x1, x2, y1, y2, done_cb);
+#else
+       /* Do nothing then... except avoid lint/compiler warnings */
+       (void)x1;
+       (void)x2;
+       (void)y1;
+       (void)y2;
+       (void)done_cb;
+#endif
+}
+
+void mddi_window_adjust(struct msm_fb_data_type *mfd,
+                       uint16 x1, uint16 x2, uint16 y1, uint16 y2)
+{
+       mddi_window_adjust_ext(mfd, x1, x2, y1, y2, NULL);
+}
diff --git a/drivers/staging/msm/mddihost.h b/drivers/staging/msm/mddihost.h
new file mode 100644 (file)
index 0000000..20b8178
--- /dev/null
@@ -0,0 +1,225 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDDIHOST_H
+#define MDDIHOST_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb_panel.h"
+
+#undef FEATURE_MDDI_MC4
+#undef FEATURE_MDDI_S6D0142
+#undef FEATURE_MDDI_HITACHI
+#define FEATURE_MDDI_SHARP
+#define FEATURE_MDDI_TOSHIBA
+#undef FEATURE_MDDI_E751
+#define FEATURE_MDDI_CORONA
+#define FEATURE_MDDI_PRISM
+
+#define T_MSM7500
+
+typedef enum {
+       format_16bpp,
+       format_18bpp,
+       format_24bpp
+} mddi_video_format;
+
+typedef enum {
+       MDDI_LCD_NONE = 0,
+       MDDI_LCD_MC4,
+       MDDI_LCD_S6D0142,
+       MDDI_LCD_SHARP,
+       MDDI_LCD_E751,
+       MDDI_LCD_CORONA,
+       MDDI_LCD_HITACHI,
+       MDDI_LCD_TOSHIBA,
+       MDDI_LCD_PRISM,
+       MDDI_LCD_TP2,
+       MDDI_NUM_LCD_TYPES,
+       MDDI_LCD_DEFAULT = MDDI_LCD_TOSHIBA
+} mddi_lcd_type;
+
+typedef enum {
+       MDDI_HOST_PRIM = 0,
+       MDDI_HOST_EXT,
+       MDDI_NUM_HOST_CORES
+} mddi_host_type;
+
+typedef enum {
+       MDDI_DRIVER_RESET,      /* host core registers have not been written. */
+       MDDI_DRIVER_DISABLED,   /* registers written, interrupts disabled. */
+       MDDI_DRIVER_ENABLED     /* registers written, interrupts enabled. */
+} mddi_host_driver_state_type;
+
+typedef enum {
+       MDDI_GPIO_INT_0 = 0,
+       MDDI_GPIO_INT_1,
+       MDDI_GPIO_INT_2,
+       MDDI_GPIO_INT_3,
+       MDDI_GPIO_INT_4,
+       MDDI_GPIO_INT_5,
+       MDDI_GPIO_INT_6,
+       MDDI_GPIO_INT_7,
+       MDDI_GPIO_INT_8,
+       MDDI_GPIO_INT_9,
+       MDDI_GPIO_INT_10,
+       MDDI_GPIO_INT_11,
+       MDDI_GPIO_INT_12,
+       MDDI_GPIO_INT_13,
+       MDDI_GPIO_INT_14,
+       MDDI_GPIO_INT_15,
+       MDDI_GPIO_NUM_INTS
+} mddi_gpio_int_type;
+
+enum mddi_data_packet_size_type {
+       MDDI_DATA_PACKET_4_BYTES  = 4,
+       MDDI_DATA_PACKET_8_BYTES  = 8,
+       MDDI_DATA_PACKET_12_BYTES = 12,
+       MDDI_DATA_PACKET_16_BYTES = 16,
+       MDDI_DATA_PACKET_24_BYTES = 24
+};
+
+typedef struct {
+       uint32 addr;
+       uint32 value;
+} mddi_reg_write_type;
+
+boolean mddi_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg);
+
+typedef void (*mddi_llist_done_cb_type) (void);
+
+typedef void (*mddi_rev_handler_type) (void *);
+
+boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type);
+
+#define MDDI_DEFAULT_PRIM_PIX_ATTR 0xC3
+#define MDDI_DEFAULT_SECD_PIX_ATTR 0xC0
+
+typedef int gpio_int_polarity_type;
+typedef int gpio_int_handler_type;
+
+typedef struct {
+       void (*vsync_detected) (boolean);
+} mddi_lcd_func_type;
+
+extern mddi_lcd_func_type mddi_lcd;
+void mddi_init(void);
+
+void mddi_powerdown(void);
+
+void mddi_host_start_ext_display(void);
+void mddi_host_stop_ext_display(void);
+
+extern spinlock_t mddi_host_spin_lock;
+#ifdef T_MSM7500
+void mddi_reset(void);
+#ifdef FEATURE_DUAL_PROC_MODEM_DISPLAY
+void mddi_host_switch_proc_control(boolean on);
+#endif
+#endif
+void mddi_host_exit_power_collapse(void);
+
+void mddi_queue_splash_screen
+    (void *buf_ptr,
+     boolean clear_area,
+     int16 src_width,
+     int16 src_starting_row,
+     int16 src_starting_column,
+     int16 num_of_rows,
+     int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
+
+void mddi_queue_image
+    (void *buf_ptr,
+     uint8 stereo_video,
+     boolean clear_area,
+     int16 src_width,
+     int16 src_starting_row,
+     int16 src_starting_column,
+     int16 num_of_rows,
+     int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
+
+int mddi_host_register_read
+    (uint32 reg_addr,
+     uint32 *reg_value_ptr, boolean wait, mddi_host_type host_idx);
+int mddi_host_register_write
+    (uint32 reg_addr, uint32 reg_val,
+     enum mddi_data_packet_size_type packet_size,
+     boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host);
+boolean mddi_host_register_write_int
+    (uint32 reg_addr,
+     uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host);
+boolean mddi_host_register_read_int
+    (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host_idx);
+void mddi_queue_register_write_static
+    (uint32 reg_addr,
+     uint32 reg_val, boolean wait, mddi_llist_done_cb_type done_cb);
+void mddi_queue_static_window_adjust
+    (const mddi_reg_write_type *reg_write,
+     uint16 num_writes, mddi_llist_done_cb_type done_cb);
+
+#define mddi_queue_register_read(reg, val_ptr, wait, sig) \
+       mddi_host_register_read(reg, val_ptr, wait, MDDI_HOST_PRIM)
+#define mddi_queue_register_write(reg, val, wait, sig) \
+       mddi_host_register_write(reg, val, MDDI_DATA_PACKET_4_BYTES,\
+       wait, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_write_extn(reg, val, pkt_size, wait, sig) \
+       mddi_host_register_write(reg, val, pkt_size, \
+       wait, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_write_int(reg, val) \
+       mddi_host_register_write_int(reg, val, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_read_int(reg, val_ptr) \
+       mddi_host_register_read_int(reg, val_ptr, MDDI_HOST_PRIM)
+#define mddi_queue_register_writes(reg_ptr, val, wait, sig) \
+       mddi_host_register_writes(reg_ptr, val, wait, sig, MDDI_HOST_PRIM)
+
+void mddi_wait(uint16 time_ms);
+void mddi_assign_max_pkt_dimensions(uint16 image_cols,
+                                   uint16 image_rows,
+                                   uint16 bpp,
+                                   uint16 *max_cols, uint16 * max_rows);
+uint16 mddi_assign_pkt_height(uint16 pkt_width, uint16 pkt_height, uint16 bpp);
+void mddi_queue_reverse_encapsulation(boolean wait);
+void mddi_disable(int lock);
+#endif /* MDDIHOST_H */
diff --git a/drivers/staging/msm/mddihost_e.c b/drivers/staging/msm/mddihost_e.c
new file mode 100644 (file)
index 0000000..7de5eda
--- /dev/null
@@ -0,0 +1,63 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#include <linux/clk.h>
+#include <mach/clk.h>
+
+extern struct semaphore mddi_host_mutex;
+static boolean mddi_host_ext_powered = FALSE;
+
+void mddi_host_start_ext_display(void)
+{
+       down(&mddi_host_mutex);
+
+       if (!mddi_host_ext_powered) {
+               mddi_host_init(MDDI_HOST_EXT);
+
+               mddi_host_ext_powered = TRUE;
+       }
+
+       up(&mddi_host_mutex);
+}
+
+void mddi_host_stop_ext_display(void)
+{
+       down(&mddi_host_mutex);
+
+       if (mddi_host_ext_powered) {
+               mddi_host_powerdown(MDDI_HOST_EXT);
+
+               mddi_host_ext_powered = FALSE;
+       }
+
+       up(&mddi_host_mutex);
+}
diff --git a/drivers/staging/msm/mddihosti.c b/drivers/staging/msm/mddihosti.c
new file mode 100644 (file)
index 0000000..f9d6e91
--- /dev/null
@@ -0,0 +1,2239 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb_panel.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#define FEATURE_MDDI_UNDERRUN_RECOVERY
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static void mddi_read_rev_packet(byte *data_ptr);
+#endif
+
+struct timer_list mddi_host_timer;
+
+#define MDDI_DEFAULT_TIMER_LENGTH 5000 /* 5 seconds */
+uint32 mddi_rtd_frequency = 60000;     /* send RTD every 60 seconds */
+uint32 mddi_client_status_frequency = 60000;   /* get status pkt every 60 secs */
+
+boolean mddi_vsync_detect_enabled = FALSE;
+mddi_gpio_info_type mddi_gpio;
+
+uint32 mddi_host_core_version;
+boolean mddi_debug_log_statistics = FALSE;
+/* #define FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION */
+/* default to TRUE in case MDP does not vote */
+static boolean mddi_host_mdp_active_flag = TRUE;
+static uint32 mddi_log_stats_counter;
+uint32 mddi_log_stats_frequency = 4000;
+
+#define MDDI_DEFAULT_REV_PKT_SIZE            0x20
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static boolean mddi_rev_ptr_workaround = TRUE;
+static uint32 mddi_reg_read_retry;
+static uint32 mddi_reg_read_retry_max = 20;
+static boolean mddi_enable_reg_read_retry = TRUE;
+static boolean mddi_enable_reg_read_retry_once = FALSE;
+
+#define MDDI_MAX_REV_PKT_SIZE                0x60
+
+#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE  0x60
+
+#define MDDI_VIDEO_REV_PKT_SIZE              0x40
+#define MDDI_REV_BUFFER_SIZE  MDDI_MAX_REV_PKT_SIZE
+static byte rev_packet_data[MDDI_MAX_REV_PKT_SIZE];
+#endif /* FEATURE_MDDI_DISABLE_REVERSE */
+/* leave these variables so graphics will compile */
+
+#define MDDI_MAX_REV_DATA_SIZE  128
+/*lint -d__align(x) */
+boolean mddi_debug_clear_rev_data = TRUE;
+
+uint32 *mddi_reg_read_value_ptr;
+
+mddi_client_capability_type mddi_client_capability_pkt;
+static boolean mddi_client_capability_request = FALSE;
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+
+#define MAX_MDDI_REV_HANDLERS 2
+#define INVALID_PKT_TYPE 0xFFFF
+
+typedef struct {
+       mddi_rev_handler_type handler;  /* ISR to be executed */
+       uint16 pkt_type;
+} mddi_rev_pkt_handler_type;
+static mddi_rev_pkt_handler_type mddi_rev_pkt_handler[MAX_MDDI_REV_HANDLERS] =
+    { {NULL, INVALID_PKT_TYPE}, {NULL, INVALID_PKT_TYPE} };
+
+static boolean mddi_rev_encap_user_request = FALSE;
+static mddi_linked_list_notify_type mddi_rev_user;
+
+spinlock_t mddi_host_spin_lock;
+extern uint32 mdp_in_processing;
+#endif
+
+typedef enum {
+       MDDI_REV_IDLE
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+           , MDDI_REV_REG_READ_ISSUED,
+       MDDI_REV_REG_READ_SENT,
+       MDDI_REV_ENCAP_ISSUED,
+       MDDI_REV_STATUS_REQ_ISSUED,
+       MDDI_REV_CLIENT_CAP_ISSUED
+#endif
+} mddi_rev_link_state_type;
+
+typedef enum {
+       MDDI_LINK_DISABLED,
+       MDDI_LINK_HIBERNATING,
+       MDDI_LINK_ACTIVATING,
+       MDDI_LINK_ACTIVE
+} mddi_host_link_state_type;
+
+typedef struct {
+       uint32 count;
+       uint32 in_count;
+       uint32 disp_req_count;
+       uint32 state_change_count;
+       uint32 ll_done_count;
+       uint32 rev_avail_count;
+       uint32 error_count;
+       uint32 rev_encap_count;
+       uint32 llist_ptr_write_1;
+       uint32 llist_ptr_write_2;
+} mddi_host_int_type;
+
+typedef struct {
+       uint32 fwd_crc_count;
+       uint32 rev_crc_count;
+       uint32 pri_underflow;
+       uint32 sec_underflow;
+       uint32 rev_overflow;
+       uint32 pri_overwrite;
+       uint32 sec_overwrite;
+       uint32 rev_overwrite;
+       uint32 dma_failure;
+       uint32 rtd_failure;
+       uint32 reg_read_failure;
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+       uint32 pri_underrun_detected;
+#endif
+} mddi_host_stat_type;
+
+typedef struct {
+       uint32 rtd_cnt;
+       uint32 rev_enc_cnt;
+       uint32 vid_cnt;
+       uint32 reg_acc_cnt;
+       uint32 cli_stat_cnt;
+       uint32 cli_cap_cnt;
+       uint32 reg_read_cnt;
+       uint32 link_active_cnt;
+       uint32 link_hibernate_cnt;
+       uint32 vsync_response_cnt;
+       uint32 fwd_crc_cnt;
+       uint32 rev_crc_cnt;
+} mddi_log_params_struct_type;
+
+typedef struct {
+       uint32 rtd_value;
+       uint32 rtd_counter;
+       uint32 client_status_cnt;
+       boolean rev_ptr_written;
+       uint8 *rev_ptr_start;
+       uint8 *rev_ptr_curr;
+       uint32 mddi_rev_ptr_write_val;
+       dma_addr_t rev_data_dma_addr;
+       uint16 rev_pkt_size;
+       mddi_rev_link_state_type rev_state;
+       mddi_host_link_state_type link_state;
+       mddi_host_driver_state_type driver_state;
+       boolean disable_hibernation;
+       uint32 saved_int_reg;
+       uint32 saved_int_en;
+       mddi_linked_list_type *llist_ptr;
+       dma_addr_t llist_dma_addr;
+       mddi_linked_list_type *llist_dma_ptr;
+       uint32 *rev_data_buf;
+       struct completion mddi_llist_avail_comp;
+       boolean mddi_waiting_for_llist_avail;
+       mddi_host_int_type int_type;
+       mddi_host_stat_type stats;
+       mddi_log_params_struct_type log_parms;
+       mddi_llist_info_type llist_info;
+       mddi_linked_list_notify_type llist_notify[MDDI_MAX_NUM_LLIST_ITEMS];
+} mddi_host_cntl_type;
+
+static mddi_host_type mddi_curr_host = MDDI_HOST_PRIM;
+static mddi_host_cntl_type mhctl[MDDI_NUM_HOST_CORES];
+mddi_linked_list_type *llist_extern[MDDI_NUM_HOST_CORES];
+mddi_linked_list_type *llist_dma_extern[MDDI_NUM_HOST_CORES];
+mddi_linked_list_notify_type *llist_extern_notify[MDDI_NUM_HOST_CORES];
+static mddi_log_params_struct_type prev_parms[MDDI_NUM_HOST_CORES];
+
+extern uint32 mdp_total_vdopkts;
+
+static boolean mddi_host_io_clock_on = FALSE;
+static boolean mddi_host_hclk_on = FALSE;
+
+int int_mddi_pri_flag = FALSE;
+int int_mddi_ext_flag = FALSE;
+
+static void mddi_report_errors(uint32 int_reg)
+{
+       mddi_host_type host_idx = mddi_curr_host;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       if (int_reg & MDDI_INT_PRI_UNDERFLOW) {
+               pmhctl->stats.pri_underflow++;
+               MDDI_MSG_ERR("!!! MDDI Primary Underflow !!!\n");
+       }
+       if (int_reg & MDDI_INT_SEC_UNDERFLOW) {
+               pmhctl->stats.sec_underflow++;
+               MDDI_MSG_ERR("!!! MDDI Secondary Underflow !!!\n");
+       }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+       if (int_reg & MDDI_INT_REV_OVERFLOW) {
+               pmhctl->stats.rev_overflow++;
+               MDDI_MSG_ERR("!!! MDDI Reverse Overflow !!!\n");
+               pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+               mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
+
+       }
+       if (int_reg & MDDI_INT_CRC_ERROR)
+               MDDI_MSG_ERR("!!! MDDI Reverse CRC Error !!!\n");
+#endif
+       if (int_reg & MDDI_INT_PRI_OVERWRITE) {
+               pmhctl->stats.pri_overwrite++;
+               MDDI_MSG_ERR("!!! MDDI Primary Overwrite !!!\n");
+       }
+       if (int_reg & MDDI_INT_SEC_OVERWRITE) {
+               pmhctl->stats.sec_overwrite++;
+               MDDI_MSG_ERR("!!! MDDI Secondary Overwrite !!!\n");
+       }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+       if (int_reg & MDDI_INT_REV_OVERWRITE) {
+               pmhctl->stats.rev_overwrite++;
+               /* This will show up normally and is not a problem */
+               MDDI_MSG_DEBUG("MDDI Reverse Overwrite!\n");
+       }
+       if (int_reg & MDDI_INT_RTD_FAILURE) {
+               mddi_host_reg_outm(INTEN, MDDI_INT_RTD_FAILURE, 0);
+               pmhctl->stats.rtd_failure++;
+               MDDI_MSG_ERR("!!! MDDI RTD Failure !!!\n");
+       }
+#endif
+       if (int_reg & MDDI_INT_DMA_FAILURE) {
+               pmhctl->stats.dma_failure++;
+               MDDI_MSG_ERR("!!! MDDI DMA Abort !!!\n");
+       }
+}
+
+static void mddi_host_enable_io_clock(void)
+{
+       if (!MDDI_HOST_IS_IO_CLOCK_ON)
+               MDDI_HOST_ENABLE_IO_CLOCK;
+}
+
+static void mddi_host_enable_hclk(void)
+{
+
+       if (!MDDI_HOST_IS_HCLK_ON)
+               MDDI_HOST_ENABLE_HCLK;
+}
+
+static void mddi_host_disable_io_clock(void)
+{
+#ifndef FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
+       if (MDDI_HOST_IS_IO_CLOCK_ON)
+               MDDI_HOST_DISABLE_IO_CLOCK;
+#endif
+}
+
+static void mddi_host_disable_hclk(void)
+{
+#ifndef FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
+       if (MDDI_HOST_IS_HCLK_ON)
+               MDDI_HOST_DISABLE_HCLK;
+#endif
+}
+
+static void mddi_vote_to_sleep(mddi_host_type host_idx, boolean sleep)
+{
+       uint16 vote_mask;
+
+       if (host_idx == MDDI_HOST_PRIM)
+               vote_mask = 0x01;
+       else
+               vote_mask = 0x02;
+}
+
+static void mddi_report_state_change(uint32 int_reg)
+{
+       mddi_host_type host_idx = mddi_curr_host;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       if ((pmhctl->saved_int_reg & MDDI_INT_IN_HIBERNATION) &&
+           (pmhctl->saved_int_reg & MDDI_INT_LINK_ACTIVE)) {
+               /* recover from condition where the io_clock was turned off by the
+                  clock driver during a transition to hibernation. The io_clock
+                  disable is to prevent MDP/MDDI underruns when changing ARM
+                  clock speeds. In the process of halting the ARM, the hclk
+                  divider needs to be set to 1. When it is set to 1, there is
+                  a small time (usecs) when hclk is off or slow, and this can
+                  cause an underrun. To prevent the underrun, clock driver turns
+                  off the MDDI io_clock before making the change. */
+               mddi_host_reg_out(CMD, MDDI_CMD_POWERUP);
+       }
+
+       if (int_reg & MDDI_INT_LINK_ACTIVE) {
+               pmhctl->link_state = MDDI_LINK_ACTIVE;
+               pmhctl->log_parms.link_active_cnt++;
+               pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
+               MDDI_MSG_DEBUG("!!! MDDI Active RTD:0x%x!!!\n",
+                              pmhctl->rtd_value);
+               /* now interrupt on hibernation */
+               mddi_host_reg_outm(INTEN,
+                                  (MDDI_INT_IN_HIBERNATION |
+                                   MDDI_INT_LINK_ACTIVE),
+                                  MDDI_INT_IN_HIBERNATION);
+
+#ifdef DEBUG_MDDIHOSTI
+               /* if gpio interrupt is enabled, start polling at fastest
+                * registered rate
+                */
+               if (mddi_gpio.polling_enabled) {
+                       timer_reg(&mddi_gpio_poll_timer,
+               mddi_gpio_poll_timer_cb, 0, mddi_gpio.polling_interval, 0);
+               }
+#endif
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+               if (mddi_rev_ptr_workaround) {
+                       /* HW CR: need to reset reverse register stuff */
+                       pmhctl->rev_ptr_written = FALSE;
+                       pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+               }
+#endif
+               /* vote on sleep */
+               mddi_vote_to_sleep(host_idx, FALSE);
+
+               if (host_idx == MDDI_HOST_PRIM) {
+                       if (mddi_vsync_detect_enabled) {
+                               /*
+                                * Indicate to client specific code that vsync
+                                * was enabled, but we did not detect a client
+                                * intiated wakeup. The client specific
+                                * handler can either reassert vsync detection,
+                                * or treat this as a valid vsync.
+                                */
+                               mddi_client_lcd_vsync_detected(FALSE);
+                               pmhctl->log_parms.vsync_response_cnt++;
+                       }
+               }
+       }
+       if (int_reg & MDDI_INT_IN_HIBERNATION) {
+               pmhctl->link_state = MDDI_LINK_HIBERNATING;
+               pmhctl->log_parms.link_hibernate_cnt++;
+               MDDI_MSG_DEBUG("!!! MDDI Hibernating !!!\n");
+               /* now interrupt on link_active */
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+               mddi_host_reg_outm(INTEN,
+                                  (MDDI_INT_MDDI_IN |
+                                   MDDI_INT_IN_HIBERNATION |
+                                   MDDI_INT_LINK_ACTIVE),
+                                  MDDI_INT_LINK_ACTIVE);
+#else
+               mddi_host_reg_outm(INTEN,
+                                  (MDDI_INT_MDDI_IN |
+                                   MDDI_INT_IN_HIBERNATION |
+                                   MDDI_INT_LINK_ACTIVE),
+                                  (MDDI_INT_MDDI_IN | MDDI_INT_LINK_ACTIVE));
+
+               pmhctl->rtd_counter = mddi_rtd_frequency;
+
+               if (pmhctl->rev_state != MDDI_REV_IDLE) {
+                       /* a rev_encap will not wake up the link, so we do that here */
+                       pmhctl->link_state = MDDI_LINK_ACTIVATING;
+                       mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+               }
+#endif
+
+               if (pmhctl->disable_hibernation) {
+                       mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+                       mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+                       pmhctl->link_state = MDDI_LINK_ACTIVATING;
+               }
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+               if ((pmhctl->llist_info.transmitting_start_idx !=
+                    UNASSIGNED_INDEX)
+                   &&
+                   ((pmhctl->
+                     saved_int_reg & (MDDI_INT_PRI_LINK_LIST_DONE |
+                                      MDDI_INT_PRI_PTR_READ)) ==
+                    MDDI_INT_PRI_PTR_READ)) {
+                       mddi_linked_list_type *llist_dma;
+                       llist_dma = pmhctl->llist_dma_ptr;
+                       /*
+                        * All indications are that we have not received a
+                        * linked list done interrupt, due to an underrun
+                        * condition. Recovery attempt is to send again.
+                        */
+                       dma_coherent_pre_ops();
+                       /* Write to primary pointer register again */
+                       mddi_host_reg_out(PRI_PTR,
+                                         &llist_dma[pmhctl->llist_info.
+                                                    transmitting_start_idx]);
+                       pmhctl->stats.pri_underrun_detected++;
+               }
+#endif
+
+               /* vote on sleep */
+               if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+                       mddi_vote_to_sleep(host_idx, TRUE);
+               }
+
+#ifdef DEBUG_MDDIHOSTI
+               /* need to stop polling timer */
+               if (mddi_gpio.polling_enabled) {
+                       (void) timer_clr(&mddi_gpio_poll_timer, T_NONE);
+               }
+#endif
+       }
+}
+
+void mddi_host_timer_service(unsigned long data)
+{
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+       unsigned long flags;
+#endif
+       mddi_host_type host_idx;
+       mddi_host_cntl_type *pmhctl;
+
+       unsigned long time_ms = MDDI_DEFAULT_TIMER_LENGTH;
+       init_timer(&mddi_host_timer);
+       mddi_host_timer.function = mddi_host_timer_service;
+       mddi_host_timer.data = 0;
+
+       mddi_host_timer.expires = jiffies + ((time_ms * HZ) / 1000);
+       add_timer(&mddi_host_timer);
+
+       for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
+            host_idx++) {
+               pmhctl = &(mhctl[host_idx]);
+               mddi_log_stats_counter += (uint32) time_ms;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+               pmhctl->rtd_counter += (uint32) time_ms;
+               pmhctl->client_status_cnt += (uint32) time_ms;
+
+               if (host_idx == MDDI_HOST_PRIM) {
+                       if (pmhctl->client_status_cnt >=
+                           mddi_client_status_frequency) {
+                               if ((pmhctl->link_state ==
+                                    MDDI_LINK_HIBERNATING)
+                                   && (pmhctl->client_status_cnt >
+                                       mddi_client_status_frequency)) {
+                                       /*
+                                        * special case where we are hibernating
+                                        * and mddi_host_isr is not firing, so
+                                        * kick the link so that the status can
+                                        * be retrieved
+                                        */
+
+                                       /* need to wake up link before issuing
+                                        * rev encap command
+                                        */
+                                       MDDI_MSG_INFO("wake up link!\n");
+                                       spin_lock_irqsave(&mddi_host_spin_lock,
+                                                         flags);
+                                       mddi_host_enable_hclk();
+                                       mddi_host_enable_io_clock();
+                                       pmhctl->link_state =
+                                           MDDI_LINK_ACTIVATING;
+                                       mddi_host_reg_out(CMD,
+                                                         MDDI_CMD_LINK_ACTIVE);
+                                       spin_unlock_irqrestore
+                                           (&mddi_host_spin_lock, flags);
+                               } else
+                                   if ((pmhctl->link_state == MDDI_LINK_ACTIVE)
+                                       && pmhctl->disable_hibernation) {
+                                       /*
+                                        * special case where we have disabled
+                                        * hibernation and mddi_host_isr
+                                        * is not firing, so enable interrupt
+                                        * for no pkts pending, which will
+                                        * generate an interrupt
+                                        */
+                                       MDDI_MSG_INFO("kick isr!\n");
+                                       spin_lock_irqsave(&mddi_host_spin_lock,
+                                                         flags);
+                                       mddi_host_enable_hclk();
+                                       mddi_host_reg_outm(INTEN,
+                                                          MDDI_INT_NO_CMD_PKTS_PEND,
+                                                          MDDI_INT_NO_CMD_PKTS_PEND);
+                                       spin_unlock_irqrestore
+                                           (&mddi_host_spin_lock, flags);
+                               }
+                       }
+               }
+#endif /* #ifndef FEATURE_MDDI_DISABLE_REVERSE */
+       }
+
+       /* Check if logging is turned on */
+       for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
+            host_idx++) {
+               mddi_log_params_struct_type *prev_ptr = &(prev_parms[host_idx]);
+               pmhctl = &(mhctl[host_idx]);
+
+               if (mddi_debug_log_statistics) {
+
+                       /* get video pkt count from MDP, since MDDI sw cannot know this */
+                       pmhctl->log_parms.vid_cnt = mdp_total_vdopkts;
+
+                       if (mddi_log_stats_counter >= mddi_log_stats_frequency) {
+                               /* mddi_log_stats_counter = 0; */
+                               if (mddi_debug_log_statistics) {
+                                       MDDI_MSG_NOTICE
+                                           ("MDDI Statistics since last report:\n");
+                                       MDDI_MSG_NOTICE("  Packets sent:\n");
+                                       MDDI_MSG_NOTICE
+                                           ("    %d RTD packet(s)\n",
+                                            pmhctl->log_parms.rtd_cnt -
+                                            prev_ptr->rtd_cnt);
+                                       if (prev_ptr->rtd_cnt !=
+                                           pmhctl->log_parms.rtd_cnt) {
+                                               unsigned long flags;
+                                               spin_lock_irqsave
+                                                   (&mddi_host_spin_lock,
+                                                    flags);
+                                               mddi_host_enable_hclk();
+                                               pmhctl->rtd_value =
+                                                   mddi_host_reg_in(RTD_VAL);
+                                               spin_unlock_irqrestore
+                                                   (&mddi_host_spin_lock,
+                                                    flags);
+                                               MDDI_MSG_NOTICE
+                                                   ("      RTD value=%d\n",
+                                                    pmhctl->rtd_value);
+                                       }
+                                       MDDI_MSG_NOTICE
+                                           ("    %d VIDEO packets\n",
+                                            pmhctl->log_parms.vid_cnt -
+                                            prev_ptr->vid_cnt);
+                                       MDDI_MSG_NOTICE
+                                           ("    %d Register Access packets\n",
+                                            pmhctl->log_parms.reg_acc_cnt -
+                                            prev_ptr->reg_acc_cnt);
+                                       MDDI_MSG_NOTICE
+                                           ("    %d Reverse Encapsulation packet(s)\n",
+                                            pmhctl->log_parms.rev_enc_cnt -
+                                            prev_ptr->rev_enc_cnt);
+                                       if (prev_ptr->rev_enc_cnt !=
+                                           pmhctl->log_parms.rev_enc_cnt) {
+                                               /* report # of reverse CRC errors */
+                                               MDDI_MSG_NOTICE
+                                                   ("      %d reverse CRC errors detected\n",
+                                                    pmhctl->log_parms.
+                                                    rev_crc_cnt -
+                                                    prev_ptr->rev_crc_cnt);
+                                       }
+                                       MDDI_MSG_NOTICE
+                                           ("  Packets received:\n");
+                                       MDDI_MSG_NOTICE
+                                           ("    %d Client Status packets",
+                                            pmhctl->log_parms.cli_stat_cnt -
+                                            prev_ptr->cli_stat_cnt);
+                                       if (prev_ptr->cli_stat_cnt !=
+                                           pmhctl->log_parms.cli_stat_cnt) {
+                                               MDDI_MSG_NOTICE
+                                                   ("      %d forward CRC errors reported\n",
+                                                    pmhctl->log_parms.
+                                                    fwd_crc_cnt -
+                                                    prev_ptr->fwd_crc_cnt);
+                                       }
+                                       MDDI_MSG_NOTICE
+                                           ("    %d Register Access Read packets\n",
+                                            pmhctl->log_parms.reg_read_cnt -
+                                            prev_ptr->reg_read_cnt);
+
+                                       if (pmhctl->link_state ==
+                                           MDDI_LINK_ACTIVE) {
+                                               MDDI_MSG_NOTICE
+                                                   ("  Current Link Status: Active\n");
+                                       } else
+                                           if ((pmhctl->link_state ==
+                                                MDDI_LINK_HIBERNATING)
+                                               || (pmhctl->link_state ==
+                                                   MDDI_LINK_ACTIVATING)) {
+                                               MDDI_MSG_NOTICE
+                                                   ("  Current Link Status: Hibernation\n");
+                                       } else {
+                                               MDDI_MSG_NOTICE
+                                                   ("  Current Link Status: Inactive\n");
+                                       }
+                                       MDDI_MSG_NOTICE
+                                           ("    Active state entered %d times\n",
+                                            pmhctl->log_parms.link_active_cnt -
+                                            prev_ptr->link_active_cnt);
+                                       MDDI_MSG_NOTICE
+                                           ("    Hibernation state entered %d times\n",
+                                            pmhctl->log_parms.
+                                            link_hibernate_cnt -
+                                            prev_ptr->link_hibernate_cnt);
+                               }
+                       }
+                       prev_parms[host_idx] = pmhctl->log_parms;
+               }
+       }
+       if (mddi_log_stats_counter >= mddi_log_stats_frequency)
+               mddi_log_stats_counter = 0;
+
+       return;
+}                              /* mddi_host_timer_cb */
+
+static void mddi_process_link_list_done(void)
+{
+       mddi_host_type host_idx = mddi_curr_host;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       /* normal forward linked list packet(s) were sent */
+       if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
+               MDDI_MSG_ERR("**** getting LL done, but no list ****\n");
+       } else {
+               uint16 idx;
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+               if (pmhctl->rev_state == MDDI_REV_REG_READ_ISSUED) {
+                       /* special case where a register read packet was sent */
+                       pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
+                       if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
+                               MDDI_MSG_ERR
+                                   ("**** getting LL done, but no list ****\n");
+                       }
+               }
+#endif
+               for (idx = pmhctl->llist_info.transmitting_start_idx;;) {
+                       uint16 next_idx = pmhctl->llist_notify[idx].next_idx;
+                       /* with reg read we don't release the waiting tcb until after
+                        * the reverse encapsulation has completed.
+                        */
+                       if (idx != pmhctl->llist_info.reg_read_idx) {
+                               /* notify task that may be waiting on this completion */
+                               if (pmhctl->llist_notify[idx].waiting) {
+                                       complete(&
+                                                (pmhctl->llist_notify[idx].
+                                                 done_comp));
+                               }
+                               if (pmhctl->llist_notify[idx].done_cb != NULL) {
+                                       (*(pmhctl->llist_notify[idx].done_cb))
+                                           ();
+                               }
+
+                               pmhctl->llist_notify[idx].in_use = FALSE;
+                               pmhctl->llist_notify[idx].waiting = FALSE;
+                               pmhctl->llist_notify[idx].done_cb = NULL;
+                               if (idx < MDDI_NUM_DYNAMIC_LLIST_ITEMS) {
+                                       /* static LLIST items are configured only once */
+                                       pmhctl->llist_notify[idx].next_idx =
+                                           UNASSIGNED_INDEX;
+                               }
+                               /*
+                                * currently, all linked list packets are
+                                * register access, so we can increment the
+                                * counter for that packet type here.
+                                */
+                               pmhctl->log_parms.reg_acc_cnt++;
+                       }
+                       if (idx == pmhctl->llist_info.transmitting_end_idx)
+                               break;
+                       idx = next_idx;
+                       if (idx == UNASSIGNED_INDEX)
+                               MDDI_MSG_CRIT("MDDI linked list corruption!\n");
+               }
+
+               pmhctl->llist_info.transmitting_start_idx = UNASSIGNED_INDEX;
+               pmhctl->llist_info.transmitting_end_idx = UNASSIGNED_INDEX;
+
+               if (pmhctl->mddi_waiting_for_llist_avail) {
+                       if (!
+                           (pmhctl->
+                            llist_notify[pmhctl->llist_info.next_free_idx].
+                            in_use)) {
+                               pmhctl->mddi_waiting_for_llist_avail = FALSE;
+                               complete(&(pmhctl->mddi_llist_avail_comp));
+                       }
+               }
+       }
+
+       /* Turn off MDDI_INT_PRI_LINK_LIST_DONE interrupt */
+       mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, 0);
+
+}
+
+static void mddi_queue_forward_linked_list(void)
+{
+       uint16 first_pkt_index;
+       mddi_linked_list_type *llist_dma;
+       mddi_host_type host_idx = mddi_curr_host;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+       llist_dma = pmhctl->llist_dma_ptr;
+
+       first_pkt_index = UNASSIGNED_INDEX;
+
+       if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+               if (pmhctl->llist_info.reg_read_waiting) {
+                       if (pmhctl->rev_state == MDDI_REV_IDLE) {
+                               /*
+                                * we have a register read to send and
+                                * can send it now
+                                */
+                               pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
+                               mddi_reg_read_retry = 0;
+                               first_pkt_index =
+                                   pmhctl->llist_info.waiting_start_idx;
+                               pmhctl->llist_info.reg_read_waiting = FALSE;
+                       }
+               } else
+#endif
+               {
+                       /*
+                        * not register read to worry about, go ahead and write
+                        * anything that may be on the waiting list.
+                        */
+                       first_pkt_index = pmhctl->llist_info.waiting_start_idx;
+               }
+       }
+
+       if (first_pkt_index != UNASSIGNED_INDEX) {
+               pmhctl->llist_info.transmitting_start_idx =
+                   pmhctl->llist_info.waiting_start_idx;
+               pmhctl->llist_info.transmitting_end_idx =
+                   pmhctl->llist_info.waiting_end_idx;
+               pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
+               pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
+
+               /* write to the primary pointer register */
+               MDDI_MSG_DEBUG("MDDI writing primary ptr with idx=%d\n",
+                              first_pkt_index);
+
+               pmhctl->int_type.llist_ptr_write_2++;
+
+               dma_coherent_pre_ops();
+               mddi_host_reg_out(PRI_PTR, &llist_dma[first_pkt_index]);
+
+               /* enable interrupt when complete */
+               mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
+                                  MDDI_INT_PRI_LINK_LIST_DONE);
+
+       }
+
+}
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static void mddi_read_rev_packet(byte *data_ptr)
+{
+       uint16 i, length;
+       mddi_host_type host_idx = mddi_curr_host;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       uint8 *rev_ptr_overflow =
+           (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE);
+
+       /* first determine the length and handle invalid lengths */
+       length = *pmhctl->rev_ptr_curr++;
+       if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+               pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+       length |= ((*pmhctl->rev_ptr_curr++) << 8);
+       if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+               pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+       if (length > (pmhctl->rev_pkt_size - 2)) {
+               MDDI_MSG_ERR("Invalid rev pkt length %d\n", length);
+               /* rev_pkt_size should always be <= rev_ptr_size so limit to packet size */
+               length = pmhctl->rev_pkt_size - 2;
+       }
+
+       /* If the data pointer is NULL, just increment the pmhctl->rev_ptr_curr.
+        * Loop around if necessary. Don't bother reading the data.
+        */
+       if (data_ptr == NULL) {
+               pmhctl->rev_ptr_curr += length;
+               if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+                       pmhctl->rev_ptr_curr -= MDDI_REV_BUFFER_SIZE;
+               return;
+       }
+
+       data_ptr[0] = length & 0x0ff;
+       data_ptr[1] = length >> 8;
+       data_ptr += 2;
+       /* copy the data to data_ptr byte-at-a-time */
+       for (i = 0; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow);
+            i++)
+               *data_ptr++ = *pmhctl->rev_ptr_curr++;
+       if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+               pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+       for (; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); i++)
+               *data_ptr++ = *pmhctl->rev_ptr_curr++;
+}
+
+static void mddi_process_rev_packets(void)
+{
+       uint32 rev_packet_count;
+       word i;
+       uint32 crc_errors;
+       boolean mddi_reg_read_successful = FALSE;
+       mddi_host_type host_idx = mddi_curr_host;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       pmhctl->log_parms.rev_enc_cnt++;
+       if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
+           (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED) &&
+           (pmhctl->rev_state != MDDI_REV_CLIENT_CAP_ISSUED)) {
+               MDDI_MSG_ERR("Wrong state %d for reverse int\n",
+                            pmhctl->rev_state);
+       }
+       /* Turn off MDDI_INT_REV_AVAIL interrupt */
+       mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, 0);
+
+       /* Clear rev data avail int */
+       mddi_host_reg_out(INT, MDDI_INT_REV_DATA_AVAIL);
+
+       /* Get Number of packets */
+       rev_packet_count = mddi_host_reg_in(REV_PKT_CNT);
+
+#ifndef T_MSM7500
+       /* Clear out rev packet counter */
+       mddi_host_reg_out(REV_PKT_CNT, 0x0000);
+#endif
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+       if ((pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) &&
+           (rev_packet_count > 0) &&
+           (mddi_host_core_version == 0x28 ||
+            mddi_host_core_version == 0x30)) {
+
+               uint32 int_reg;
+               uint32 max_count = 0;
+
+               mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
+               int_reg = mddi_host_reg_in(INT);
+               while ((int_reg & 0x100000) == 0) {
+                       udelay(3);
+                       int_reg = mddi_host_reg_in(INT);
+                       if (++max_count > 100)
+                               break;
+               }
+       }
+#endif
+
+       /* Get CRC error count */
+       crc_errors = mddi_host_reg_in(REV_CRC_ERR);
+       if (crc_errors != 0) {
+               pmhctl->log_parms.rev_crc_cnt += crc_errors;
+               pmhctl->stats.rev_crc_count += crc_errors;
+               MDDI_MSG_ERR("!!! MDDI %d Reverse CRC Error(s) !!!\n",
+                            crc_errors);
+#ifndef T_MSM7500
+               /* Clear CRC error count */
+               mddi_host_reg_out(REV_CRC_ERR, 0x0000);
+#endif
+               /* also issue an RTD to attempt recovery */
+               pmhctl->rtd_counter = mddi_rtd_frequency;
+       }
+
+       pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
+
+       MDDI_MSG_DEBUG("MDDI rev pkt cnt=%d, ptr=0x%x, RTD:0x%x\n",
+                      rev_packet_count,
+                      pmhctl->rev_ptr_curr - pmhctl->rev_ptr_start,
+                      pmhctl->rtd_value);
+
+       if (rev_packet_count >= 1) {
+               mddi_invalidate_cache_lines((uint32 *) pmhctl->rev_ptr_start,
+                                           MDDI_REV_BUFFER_SIZE);
+       }
+       /* order the reads */
+       dma_coherent_post_ops();
+       for (i = 0; i < rev_packet_count; i++) {
+               mddi_rev_packet_type *rev_pkt_ptr;
+
+               mddi_read_rev_packet(rev_packet_data);
+
+               rev_pkt_ptr = (mddi_rev_packet_type *) rev_packet_data;
+
+               if (rev_pkt_ptr->packet_length > pmhctl->rev_pkt_size) {
+                       MDDI_MSG_ERR("!!!invalid packet size: %d\n",
+                                    rev_pkt_ptr->packet_length);
+               }
+
+               MDDI_MSG_DEBUG("MDDI rev pkt 0x%x size 0x%x\n",
+                              rev_pkt_ptr->packet_type,
+                              rev_pkt_ptr->packet_length);
+
+               /* Do whatever you want to do with the data based on the packet type */
+               switch (rev_pkt_ptr->packet_type) {
+               case 66:        /* Client Capability */
+                       {
+                               mddi_client_capability_type
+                                   *client_capability_pkt_ptr;
+
+                               client_capability_pkt_ptr =
+                                   (mddi_client_capability_type *)
+                                   rev_packet_data;
+                               MDDI_MSG_NOTICE
+                                   ("Client Capability: Week=%d, Year=%d\n",
+                                    client_capability_pkt_ptr->
+                                    Week_of_Manufacture,
+                                    client_capability_pkt_ptr->
+                                    Year_of_Manufacture);
+                               memcpy((void *)&mddi_client_capability_pkt,
+                                      (void *)rev_packet_data,
+                                      sizeof(mddi_client_capability_type));
+                               pmhctl->log_parms.cli_cap_cnt++;
+                       }
+                       break;
+
+               case 70:        /* Display Status */
+                       {
+                               mddi_client_status_type *client_status_pkt_ptr;
+
+                               client_status_pkt_ptr =
+                                   (mddi_client_status_type *) rev_packet_data;
+                               if ((client_status_pkt_ptr->crc_error_count !=
+                                    0)
+                                   || (client_status_pkt_ptr->
+                                       reverse_link_request != 0)) {
+                                       MDDI_MSG_ERR
+                                           ("Client Status: RevReq=%d, CrcErr=%d\n",
+                                            client_status_pkt_ptr->
+                                            reverse_link_request,
+                                            client_status_pkt_ptr->
+                                            crc_error_count);
+                               } else {
+                                       MDDI_MSG_DEBUG
+                                           ("Client Status: RevReq=%d, CrcErr=%d\n",
+                                            client_status_pkt_ptr->
+                                            reverse_link_request,
+                                            client_status_pkt_ptr->
+                                            crc_error_count);
+                               }
+                               pmhctl->log_parms.fwd_crc_cnt +=
+                                   client_status_pkt_ptr->crc_error_count;
+                               pmhctl->stats.fwd_crc_count +=
+                                   client_status_pkt_ptr->crc_error_count;
+                               pmhctl->log_parms.cli_stat_cnt++;
+                       }
+                       break;
+
+               case 146:       /* register access packet */
+                       {
+                               mddi_register_access_packet_type
+                                   * regacc_pkt_ptr;
+
+                               regacc_pkt_ptr =
+                                   (mddi_register_access_packet_type *)
+                                   rev_packet_data;
+
+                               MDDI_MSG_DEBUG
+                                   ("Reg Acc parse reg=0x%x, value=0x%x\n",
+                                    regacc_pkt_ptr->register_address,
+                                    regacc_pkt_ptr->register_data_list);
+
+                               /* Copy register value to location passed in */
+                               if (mddi_reg_read_value_ptr) {
+#if defined(T_MSM6280) && !defined(T_MSM7200)
+                                       /* only least significant 16 bits are valid with 6280 */
+                                       *mddi_reg_read_value_ptr =
+                                           regacc_pkt_ptr->
+                                           register_data_list & 0x0000ffff;
+#else
+                                       *mddi_reg_read_value_ptr =
+                                           regacc_pkt_ptr->register_data_list;
+#endif
+                                       mddi_reg_read_successful = TRUE;
+                                       mddi_reg_read_value_ptr = NULL;
+                               }
+
+#ifdef DEBUG_MDDIHOSTI
+                               if ((mddi_gpio.polling_enabled) &&
+                                   (regacc_pkt_ptr->register_address ==
+                                    mddi_gpio.polling_reg)) {
+                                       /*
+                                        * ToDo: need to call Linux GPIO call
+                                        * here...
+                                        */
+                                        mddi_client_lcd_gpio_poll(
+                                        regacc_pkt_ptr->register_data_list);
+                               }
+#endif
+                               pmhctl->log_parms.reg_read_cnt++;
+                       }
+                       break;
+
+               default:        /* any other packet */
+                       {
+                               uint16 hdlr;
+
+                               for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS;
+                                    hdlr++) {
+                                       if (mddi_rev_pkt_handler[hdlr].
+                                           pkt_type ==
+                                           rev_pkt_ptr->packet_type) {
+                                               (*
+                                                (mddi_rev_pkt_handler[hdlr].
+                                                 handler)) (rev_pkt_ptr);
+                                       /* pmhctl->rev_state = MDDI_REV_IDLE; */
+                                               break;
+                                       }
+                               }
+                               if (hdlr >= MAX_MDDI_REV_HANDLERS)
+                                       MDDI_MSG_ERR("MDDI unknown rev pkt\n");
+                       }
+                       break;
+               }
+       }
+       if ((pmhctl->rev_ptr_curr + pmhctl->rev_pkt_size) >=
+           (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE)) {
+               pmhctl->rev_ptr_written = FALSE;
+       }
+
+       if (pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) {
+               pmhctl->rev_state = MDDI_REV_IDLE;
+               if (mddi_rev_user.waiting) {
+                       mddi_rev_user.waiting = FALSE;
+                       complete(&(mddi_rev_user.done_comp));
+               } else if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
+                       MDDI_MSG_ERR
+                           ("Reverse Encap state, but no reg read in progress\n");
+               } else {
+                       if ((!mddi_reg_read_successful) &&
+                           (mddi_reg_read_retry < mddi_reg_read_retry_max) &&
+                           (mddi_enable_reg_read_retry)) {
+                               /*
+                                * There is a race condition that can happen
+                                * where the reverse encapsulation message is
+                                * sent out by the MDDI host before the register
+                                * read packet is sent. As a work-around for
+                                * that problem we issue the reverse
+                                * encapsulation one more time before giving up.
+                                */
+                               if (mddi_enable_reg_read_retry_once)
+                                       mddi_reg_read_retry =
+                                           mddi_reg_read_retry_max;
+                               pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
+                               pmhctl->stats.reg_read_failure++;
+                       } else {
+                               uint16 reg_read_idx =
+                                   pmhctl->llist_info.reg_read_idx;
+
+                               mddi_reg_read_retry = 0;
+                               if (pmhctl->llist_notify[reg_read_idx].waiting) {
+                                       complete(&
+                                                (pmhctl->
+                                                 llist_notify[reg_read_idx].
+                                                 done_comp));
+                               }
+                               pmhctl->llist_info.reg_read_idx =
+                                   UNASSIGNED_INDEX;
+                               if (pmhctl->llist_notify[reg_read_idx].
+                                   done_cb != NULL) {
+                                       (*
+                                        (pmhctl->llist_notify[reg_read_idx].
+                                         done_cb)) ();
+                               }
+                               pmhctl->llist_notify[reg_read_idx].next_idx =
+                                   UNASSIGNED_INDEX;
+                               pmhctl->llist_notify[reg_read_idx].in_use =
+                                   FALSE;
+                               pmhctl->llist_notify[reg_read_idx].waiting =
+                                   FALSE;
+                               pmhctl->llist_notify[reg_read_idx].done_cb =
+                                   NULL;
+                               if (!mddi_reg_read_successful)
+                                       pmhctl->stats.reg_read_failure++;
+                       }
+               }
+       } else if (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) {
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+               if (mddi_host_core_version == 0x28 ||
+                   mddi_host_core_version == 0x30) {
+                       mddi_host_reg_out(FIFO_ALLOC, 0x00);
+                       pmhctl->rev_ptr_written = TRUE;
+                       mddi_host_reg_out(REV_PTR,
+                               pmhctl->mddi_rev_ptr_write_val);
+                       pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+                       mddi_host_reg_out(CMD, 0xC00);
+               }
+#endif
+
+               if (mddi_rev_user.waiting) {
+                       mddi_rev_user.waiting = FALSE;
+                       complete(&(mddi_rev_user.done_comp));
+               }
+               pmhctl->rev_state = MDDI_REV_IDLE;
+       } else {
+               pmhctl->rev_state = MDDI_REV_IDLE;
+       }
+
+       /* pmhctl->rev_state = MDDI_REV_IDLE; */
+
+       /* Re-enable interrupt */
+       mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL,
+                          MDDI_INT_REV_DATA_AVAIL);
+
+}
+
+static void mddi_issue_reverse_encapsulation(void)
+{
+       mddi_host_type host_idx = mddi_curr_host;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+       /* Only issue a reverse encapsulation packet if:
+        * 1) another reverse is not in progress (MDDI_REV_IDLE).
+        * 2) a register read has been sent (MDDI_REV_REG_READ_SENT).
+        * 3) forward is not in progress, because of a hw bug in client that
+        *    causes forward crc errors on packet immediately after rev encap.
+        */
+       if (((pmhctl->rev_state == MDDI_REV_IDLE) ||
+            (pmhctl->rev_state == MDDI_REV_REG_READ_SENT)) &&
+           (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+           (!mdp_in_processing)) {
+               uint32 mddi_command = MDDI_CMD_SEND_REV_ENCAP;
+
+               if ((pmhctl->rev_state == MDDI_REV_REG_READ_SENT) ||
+                   (mddi_rev_encap_user_request == TRUE)) {
+                       mddi_host_enable_io_clock();
+                       if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+                               /* need to wake up link before issuing rev encap command */
+                               MDDI_MSG_DEBUG("wake up link!\n");
+                               pmhctl->link_state = MDDI_LINK_ACTIVATING;
+                               mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+                       } else {
+                               if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
+                                       MDDI_MSG_DEBUG
+                                           ("mddi sending RTD command!\n");
+                                       mddi_host_reg_out(CMD,
+                                                         MDDI_CMD_SEND_RTD);
+                                       pmhctl->rtd_counter = 0;
+                                       pmhctl->log_parms.rtd_cnt++;
+                               }
+                               if (pmhctl->rev_state != MDDI_REV_REG_READ_SENT) {
+                                       /* this is generic reverse request by user, so
+                                        * reset the waiting flag. */
+                                       mddi_rev_encap_user_request = FALSE;
+                               }
+                               /* link is active so send reverse encap to get register read results */
+                               pmhctl->rev_state = MDDI_REV_ENCAP_ISSUED;
+                               mddi_command = MDDI_CMD_SEND_REV_ENCAP;
+                               MDDI_MSG_DEBUG("sending rev encap!\n");
+                       }
+               } else
+                   if ((pmhctl->client_status_cnt >=
+                        mddi_client_status_frequency)
+                       || mddi_client_capability_request) {
+                       mddi_host_enable_io_clock();
+                       if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+                               /* only wake up the link if it client status is overdue */
+                               if ((pmhctl->client_status_cnt >=
+                                    (mddi_client_status_frequency * 2))
+                                   || mddi_client_capability_request) {
+                                       /* need to wake up link before issuing rev encap command */
+                                       MDDI_MSG_DEBUG("wake up link!\n");
+                                       pmhctl->link_state =
+                                           MDDI_LINK_ACTIVATING;
+                                       mddi_host_reg_out(CMD,
+                                                         MDDI_CMD_LINK_ACTIVE);
+                               }
+                       } else {
+                               if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
+                                       MDDI_MSG_DEBUG
+                                           ("mddi sending RTD command!\n");
+                                       mddi_host_reg_out(CMD,
+                                                         MDDI_CMD_SEND_RTD);
+                                       pmhctl->rtd_counter = 0;
+                                       pmhctl->log_parms.rtd_cnt++;
+                               }
+                               /* periodically get client status */
+                               MDDI_MSG_DEBUG
+                                   ("mddi sending rev enc! (get status)\n");
+                               if (mddi_client_capability_request) {
+                                       pmhctl->rev_state =
+                                           MDDI_REV_CLIENT_CAP_ISSUED;
+                                       mddi_command = MDDI_CMD_GET_CLIENT_CAP;
+                                       mddi_client_capability_request = FALSE;
+                               } else {
+                                       pmhctl->rev_state =
+                                           MDDI_REV_STATUS_REQ_ISSUED;
+                                       pmhctl->client_status_cnt = 0;
+                                       mddi_command =
+                                           MDDI_CMD_GET_CLIENT_STATUS;
+                               }
+                       }
+               }
+               if ((pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) ||
+                   (pmhctl->rev_state == MDDI_REV_STATUS_REQ_ISSUED) ||
+                   (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED)) {
+                       pmhctl->int_type.rev_encap_count++;
+#if defined(T_MSM6280) && !defined(T_MSM7200)
+                       mddi_rev_pointer_written = TRUE;
+                       mddi_host_reg_out(REV_PTR, mddi_rev_ptr_write_val);
+                       mddi_rev_ptr_curr = mddi_rev_ptr_start;
+                       /* force new rev ptr command */
+                       mddi_host_reg_out(CMD, 0xC00);
+#else
+                       if (!pmhctl->rev_ptr_written) {
+                               MDDI_MSG_DEBUG("writing reverse pointer!\n");
+                               pmhctl->rev_ptr_written = TRUE;
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+                               if ((pmhctl->rev_state ==
+                                    MDDI_REV_CLIENT_CAP_ISSUED) &&
+                                   (mddi_host_core_version == 0x28 ||
+                                    mddi_host_core_version == 0x30)) {
+                                       pmhctl->rev_ptr_written = FALSE;
+                                       mddi_host_reg_out(FIFO_ALLOC, 0x02);
+                               } else
+                                       mddi_host_reg_out(REV_PTR,
+                                                 pmhctl->
+                                                 mddi_rev_ptr_write_val);
+#else
+                               mddi_host_reg_out(REV_PTR,
+                                                 pmhctl->
+                                                 mddi_rev_ptr_write_val);
+#endif
+                       }
+#endif
+                       if (mddi_debug_clear_rev_data) {
+                               uint16 i;
+                               for (i = 0; i < MDDI_MAX_REV_DATA_SIZE / 4; i++)
+                                       pmhctl->rev_data_buf[i] = 0xdddddddd;
+                               /* clean cache */
+                               mddi_flush_cache_lines(pmhctl->rev_data_buf,
+                                                      MDDI_MAX_REV_DATA_SIZE);
+                       }
+
+                       /* send reverse encapsulation to get needed data */
+                       mddi_host_reg_out(CMD, mddi_command);
+               }
+       }
+
+}
+
+static void mddi_process_client_initiated_wakeup(void)
+{
+       mddi_host_type host_idx = mddi_curr_host;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       /* Disable MDDI_INT Interrupt, we detect client initiated wakeup one
+        * time for each entry into hibernation */
+       mddi_host_reg_outm(INTEN, MDDI_INT_MDDI_IN, 0);
+
+       if (host_idx == MDDI_HOST_PRIM) {
+               if (mddi_vsync_detect_enabled) {
+                       mddi_host_enable_io_clock();
+#ifndef MDDI_HOST_DISP_LISTEN
+                       /* issue command to bring up link */
+                       /* need to do this to clear the vsync condition */
+                       if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+                               pmhctl->link_state = MDDI_LINK_ACTIVATING;
+                               mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+                       }
+#endif
+                       /*
+                        * Indicate to client specific code that vsync was
+                        * enabled, and we did not detect a client initiated
+                        * wakeup. The client specific handler can clear the
+                        * condition if necessary to prevent subsequent
+                        * client initiated wakeups.
+                        */
+                       mddi_client_lcd_vsync_detected(TRUE);
+                       pmhctl->log_parms.vsync_response_cnt++;
+                       MDDI_MSG_NOTICE("MDDI_INT_IN condition\n");
+
+               }
+       }
+
+       if (mddi_gpio.polling_enabled) {
+               mddi_host_enable_io_clock();
+               /* check interrupt status now */
+               (void)mddi_queue_register_read_int(mddi_gpio.polling_reg,
+                                                  &mddi_gpio.polling_val);
+       }
+}
+#endif /* FEATURE_MDDI_DISABLE_REVERSE */
+
+static void mddi_host_isr(void)
+{
+       uint32 int_reg, int_en;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+       uint32 status_reg;
+#endif
+       mddi_host_type host_idx = mddi_curr_host;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       if (!MDDI_HOST_IS_HCLK_ON) {
+               MDDI_HOST_ENABLE_HCLK;
+               MDDI_MSG_DEBUG("HCLK disabled, but isr is firing\n");
+       }
+       int_reg = mddi_host_reg_in(INT);
+       int_en = mddi_host_reg_in(INTEN);
+       pmhctl->saved_int_reg = int_reg;
+       pmhctl->saved_int_en = int_en;
+       int_reg = int_reg & int_en;
+       pmhctl->int_type.count++;
+
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+       status_reg = mddi_host_reg_in(STAT);
+
+       if ((int_reg & MDDI_INT_MDDI_IN) ||
+           ((int_en & MDDI_INT_MDDI_IN) &&
+            ((int_reg == 0) || (status_reg & MDDI_STAT_CLIENT_WAKEUP_REQ)))) {
+               /*
+                * The MDDI_IN condition will clear itself, and so it is
+                * possible that MDDI_IN was the reason for the isr firing,
+                * even though the interrupt register does not have the
+                * MDDI_IN bit set. To check if this was the case we need to
+                * look at the status register bit that signifies a client
+                * initiated wakeup. If the status register bit is set, as well
+                * as the MDDI_IN interrupt enabled, then we treat this as a
+                * client initiated wakeup.
+                */
+               if (int_reg & MDDI_INT_MDDI_IN)
+                       pmhctl->int_type.in_count++;
+               mddi_process_client_initiated_wakeup();
+       }
+#endif
+
+       if (int_reg & MDDI_INT_LINK_STATE_CHANGES) {
+               pmhctl->int_type.state_change_count++;
+               mddi_report_state_change(int_reg);
+       }
+
+       if (int_reg & MDDI_INT_PRI_LINK_LIST_DONE) {
+               pmhctl->int_type.ll_done_count++;
+               mddi_process_link_list_done();
+       }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+       if (int_reg & MDDI_INT_REV_DATA_AVAIL) {
+               pmhctl->int_type.rev_avail_count++;
+               mddi_process_rev_packets();
+       }
+#endif
+
+       if (int_reg & MDDI_INT_ERROR_CONDITIONS) {
+               pmhctl->int_type.error_count++;
+               mddi_report_errors(int_reg);
+
+               mddi_host_reg_out(INT, int_reg & MDDI_INT_ERROR_CONDITIONS);
+       }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+       mddi_issue_reverse_encapsulation();
+
+       if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
+           (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED))
+#endif
+               /* don't want simultaneous reverse and forward with Eagle */
+               mddi_queue_forward_linked_list();
+
+       if (int_reg & MDDI_INT_NO_CMD_PKTS_PEND) {
+               /* this interrupt is used to kick the isr when hibernation is disabled */
+               mddi_host_reg_outm(INTEN, MDDI_INT_NO_CMD_PKTS_PEND, 0);
+       }
+
+       if ((!mddi_host_mdp_active_flag) &&
+           (!mddi_vsync_detect_enabled) &&
+           (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+           (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
+           (pmhctl->rev_state == MDDI_REV_IDLE)) {
+               if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+                       mddi_host_disable_io_clock();
+                       mddi_host_disable_hclk();
+               }
+#ifdef FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION
+               else if ((pmhctl->link_state == MDDI_LINK_ACTIVE) &&
+                        (!pmhctl->disable_hibernation)) {
+                       mddi_host_reg_out(CMD, MDDI_CMD_POWERDOWN);
+               }
+#endif
+       }
+}
+
+static void mddi_host_isr_primary(void)
+{
+       mddi_curr_host = MDDI_HOST_PRIM;
+       mddi_host_isr();
+}
+
+irqreturn_t mddi_pmdh_isr_proxy(int irq, void *ptr)
+{
+       mddi_host_isr_primary();
+       return IRQ_HANDLED;
+}
+
+static void mddi_host_isr_external(void)
+{
+       mddi_curr_host = MDDI_HOST_EXT;
+       mddi_host_isr();
+       mddi_curr_host = MDDI_HOST_PRIM;
+}
+
+irqreturn_t mddi_emdh_isr_proxy(int irq, void *ptr)
+{
+       mddi_host_isr_external();
+       return IRQ_HANDLED;
+}
+
+static void mddi_host_initialize_registers(mddi_host_type host_idx)
+{
+       uint32 pad_reg_val;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
+               return;
+
+       /* turn on HCLK to MDDI host core */
+       mddi_host_enable_hclk();
+
+       /* MDDI Reset command */
+       mddi_host_reg_out(CMD, MDDI_CMD_RESET);
+
+       /* Version register (= 0x01) */
+       mddi_host_reg_out(VERSION, 0x0001);
+
+       /* Bytes per subframe register */
+       mddi_host_reg_out(BPS, MDDI_HOST_BYTES_PER_SUBFRAME);
+
+       /* Subframes per media frames register (= 0x03) */
+       mddi_host_reg_out(SPM, 0x0003);
+
+       /* Turn Around 1 register (= 0x05) */
+       mddi_host_reg_out(TA1_LEN, 0x0005);
+
+       /* Turn Around 2 register (= 0x0C) */
+       mddi_host_reg_out(TA2_LEN, MDDI_HOST_TA2_LEN);
+
+       /* Drive hi register (= 0x96) */
+       mddi_host_reg_out(DRIVE_HI, 0x0096);
+
+       /* Drive lo register (= 0x32) */
+       mddi_host_reg_out(DRIVE_LO, 0x0032);
+
+       /* Display wakeup count register (= 0x3c) */
+       mddi_host_reg_out(DISP_WAKE, 0x003c);
+
+       /* Reverse Rate Divisor register (= 0x2) */
+       mddi_host_reg_out(REV_RATE_DIV, MDDI_HOST_REV_RATE_DIV);
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+       /* Reverse Pointer Size */
+       mddi_host_reg_out(REV_SIZE, MDDI_REV_BUFFER_SIZE);
+
+       /* Rev Encap Size */
+       mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+#endif
+
+       /* Periodic Rev Encap */
+       /* don't send periodically */
+       mddi_host_reg_out(CMD, MDDI_CMD_PERIODIC_REV_ENCAP);
+
+       pad_reg_val = mddi_host_reg_in(PAD_CTL);
+       if (pad_reg_val == 0) {
+               /* If we are turning on band gap, need to wait 5us before turning
+                * on the rest of the PAD */
+               mddi_host_reg_out(PAD_CTL, 0x08000);
+               udelay(5);
+       }
+#ifdef T_MSM7200
+       /* Recommendation from PAD hw team */
+       mddi_host_reg_out(PAD_CTL, 0xa850a);
+#else
+       /* Recommendation from PAD hw team */
+       mddi_host_reg_out(PAD_CTL, 0xa850f);
+#endif
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+       mddi_host_reg_out(PAD_IO_CTL, 0x00320000);
+       mddi_host_reg_out(PAD_CAL, 0x00220020);
+#endif
+
+       mddi_host_core_version = mddi_host_reg_inm(CORE_VER, 0xffff);
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+       if (mddi_host_core_version >= 8)
+               mddi_rev_ptr_workaround = FALSE;
+       pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+#endif
+
+       if ((mddi_host_core_version > 8) && (mddi_host_core_version < 0x19))
+               mddi_host_reg_out(TEST, 0x2);
+
+       /* Need an even number for counts */
+       mddi_host_reg_out(DRIVER_START_CNT, 0x60006);
+
+#ifndef T_MSM7500
+       /* Setup defaults for MDP related register */
+       mddi_host_reg_out(MDP_VID_FMT_DES, 0x5666);
+       mddi_host_reg_out(MDP_VID_PIX_ATTR, 0x00C3);
+       mddi_host_reg_out(MDP_VID_CLIENTID, 0);
+#endif
+
+       /* automatically hibernate after 1 empty subframe */
+       if (pmhctl->disable_hibernation)
+               mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+       else
+               mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+
+       /* Bring up link if display (client) requests it */
+#ifdef MDDI_HOST_DISP_LISTEN
+       mddi_host_reg_out(CMD, MDDI_CMD_DISP_LISTEN);
+#else
+       mddi_host_reg_out(CMD, MDDI_CMD_DISP_IGNORE);
+#endif
+
+}
+
+void mddi_host_configure_interrupts(mddi_host_type host_idx, boolean enable)
+{
+       unsigned long flags;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+       /* turn on HCLK to MDDI host core if it has been disabled */
+       mddi_host_enable_hclk();
+       /* Clear MDDI Interrupt enable reg */
+       mddi_host_reg_out(INTEN, 0);
+
+       spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+       if (enable) {
+               pmhctl->driver_state = MDDI_DRIVER_ENABLED;
+
+               if (host_idx == MDDI_HOST_PRIM) {
+                       if (request_irq
+                           (INT_MDDI_PRI, mddi_pmdh_isr_proxy, IRQF_DISABLED,
+                            "PMDH", 0) != 0)
+                               printk(KERN_ERR
+                                      "a mddi: unable to request_irq\n");
+                       else
+                               int_mddi_pri_flag = TRUE;
+               } else {
+                       if (request_irq
+                           (INT_MDDI_EXT, mddi_emdh_isr_proxy, IRQF_DISABLED,
+                            "EMDH", 0) != 0)
+                               printk(KERN_ERR
+                                      "b mddi: unable to request_irq\n");
+                       else
+                               int_mddi_ext_flag = TRUE;
+               }
+
+               /* Set MDDI Interrupt enable reg -- Enable Reverse data avail */
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+               mddi_host_reg_out(INTEN,
+                                 MDDI_INT_ERROR_CONDITIONS |
+                                 MDDI_INT_LINK_STATE_CHANGES);
+#else
+               /* Reverse Pointer register */
+               pmhctl->rev_ptr_written = FALSE;
+
+               mddi_host_reg_out(INTEN,
+                                 MDDI_INT_REV_DATA_AVAIL |
+                                 MDDI_INT_ERROR_CONDITIONS |
+                                 MDDI_INT_LINK_STATE_CHANGES);
+               pmhctl->rtd_counter = mddi_rtd_frequency;
+               pmhctl->client_status_cnt = 0;
+#endif
+       } else {
+               if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
+                       pmhctl->driver_state = MDDI_DRIVER_DISABLED;
+       }
+
+}
+
+static void mddi_host_powerup(mddi_host_type host_idx)
+{
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       if (pmhctl->link_state != MDDI_LINK_DISABLED)
+               return;
+
+       /* enable IO_CLK and hclk to MDDI host core */
+       mddi_host_enable_io_clock();
+
+       mddi_host_initialize_registers(host_idx);
+       mddi_host_configure_interrupts(host_idx, TRUE);
+
+       pmhctl->link_state = MDDI_LINK_ACTIVATING;
+
+       /* Link activate command */
+       mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+
+#ifdef CLKRGM_MDDI_IO_CLOCK_IN_MHZ
+       MDDI_MSG_NOTICE("MDDI Host: Activating Link %d Mbps\n",
+                       CLKRGM_MDDI_IO_CLOCK_IN_MHZ * 2);
+#else
+       MDDI_MSG_NOTICE("MDDI Host: Activating Link\n");
+#endif
+
+       /* Initialize the timer */
+       if (host_idx == MDDI_HOST_PRIM)
+               mddi_host_timer_service(0);
+}
+
+void mddi_host_init(mddi_host_type host_idx)
+/* Write out the MDDI configuration registers */
+{
+       static boolean initialized = FALSE;
+       mddi_host_cntl_type *pmhctl;
+
+       if (host_idx >= MDDI_NUM_HOST_CORES) {
+               MDDI_MSG_ERR("Invalid host core index\n");
+               return;
+       }
+
+       if (!initialized) {
+               uint16 idx;
+               mddi_host_type host;
+               for (host = MDDI_HOST_PRIM; host < MDDI_NUM_HOST_CORES; host++) {
+                       pmhctl = &(mhctl[host]);
+                       initialized = TRUE;
+
+                       pmhctl->llist_ptr =
+                           dma_alloc_coherent(NULL, MDDI_LLIST_POOL_SIZE,
+                                              &(pmhctl->llist_dma_addr),
+                                              GFP_KERNEL);
+                       pmhctl->llist_dma_ptr =
+                           (mddi_linked_list_type *) (void *)pmhctl->
+                           llist_dma_addr;
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+                       pmhctl->rev_data_buf = NULL;
+                       if (pmhctl->llist_ptr == NULL)
+#else
+                       mddi_rev_user.waiting = FALSE;
+                       init_completion(&(mddi_rev_user.done_comp));
+                       pmhctl->rev_data_buf =
+                           dma_alloc_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
+                                              &(pmhctl->rev_data_dma_addr),
+                                              GFP_KERNEL);
+                       if ((pmhctl->llist_ptr == NULL)
+                           || (pmhctl->rev_data_buf == NULL))
+#endif
+                       {
+                               MDDI_MSG_CRIT
+                                   ("unable to alloc non-cached memory\n");
+                       }
+                       llist_extern[host] = pmhctl->llist_ptr;
+                       llist_dma_extern[host] = pmhctl->llist_dma_ptr;
+                       llist_extern_notify[host] = pmhctl->llist_notify;
+
+                       for (idx = 0; idx < UNASSIGNED_INDEX; idx++) {
+                               init_completion(&
+                                               (pmhctl->llist_notify[idx].
+                                                done_comp));
+                       }
+                       init_completion(&(pmhctl->mddi_llist_avail_comp));
+                       spin_lock_init(&mddi_host_spin_lock);
+                       pmhctl->mddi_waiting_for_llist_avail = FALSE;
+                       pmhctl->mddi_rev_ptr_write_val =
+                           (uint32) (void *)(pmhctl->rev_data_dma_addr);
+                       pmhctl->rev_ptr_start = (void *)pmhctl->rev_data_buf;
+
+                       pmhctl->rev_pkt_size = MDDI_DEFAULT_REV_PKT_SIZE;
+                       pmhctl->rev_state = MDDI_REV_IDLE;
+#ifdef IMAGE_MODEM_PROC
+                       /* assume hibernation state is last state from APPS proc, so that
+                        * we don't reinitialize the host core */
+                       pmhctl->link_state = MDDI_LINK_HIBERNATING;
+#else
+                       pmhctl->link_state = MDDI_LINK_DISABLED;
+#endif
+                       pmhctl->driver_state = MDDI_DRIVER_DISABLED;
+                       pmhctl->disable_hibernation = FALSE;
+
+                       /* initialize llist variables */
+                       pmhctl->llist_info.transmitting_start_idx =
+                           UNASSIGNED_INDEX;
+                       pmhctl->llist_info.transmitting_end_idx =
+                           UNASSIGNED_INDEX;
+                       pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
+                       pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
+                       pmhctl->llist_info.reg_read_idx = UNASSIGNED_INDEX;
+                       pmhctl->llist_info.next_free_idx =
+                           MDDI_FIRST_DYNAMIC_LLIST_IDX;
+                       pmhctl->llist_info.reg_read_waiting = FALSE;
+
+                       mddi_vsync_detect_enabled = FALSE;
+                       mddi_gpio.polling_enabled = FALSE;
+
+                       pmhctl->int_type.count = 0;
+                       pmhctl->int_type.in_count = 0;
+                       pmhctl->int_type.disp_req_count = 0;
+                       pmhctl->int_type.state_change_count = 0;
+                       pmhctl->int_type.ll_done_count = 0;
+                       pmhctl->int_type.rev_avail_count = 0;
+                       pmhctl->int_type.error_count = 0;
+                       pmhctl->int_type.rev_encap_count = 0;
+                       pmhctl->int_type.llist_ptr_write_1 = 0;
+                       pmhctl->int_type.llist_ptr_write_2 = 0;
+
+                       pmhctl->stats.fwd_crc_count = 0;
+                       pmhctl->stats.rev_crc_count = 0;
+                       pmhctl->stats.pri_underflow = 0;
+                       pmhctl->stats.sec_underflow = 0;
+                       pmhctl->stats.rev_overflow = 0;
+                       pmhctl->stats.pri_overwrite = 0;
+                       pmhctl->stats.sec_overwrite = 0;
+                       pmhctl->stats.rev_overwrite = 0;
+                       pmhctl->stats.dma_failure = 0;
+                       pmhctl->stats.rtd_failure = 0;
+                       pmhctl->stats.reg_read_failure = 0;
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+                       pmhctl->stats.pri_underrun_detected = 0;
+#endif
+
+                       pmhctl->log_parms.rtd_cnt = 0;
+                       pmhctl->log_parms.rev_enc_cnt = 0;
+                       pmhctl->log_parms.vid_cnt = 0;
+                       pmhctl->log_parms.reg_acc_cnt = 0;
+                       pmhctl->log_parms.cli_stat_cnt = 0;
+                       pmhctl->log_parms.cli_cap_cnt = 0;
+                       pmhctl->log_parms.reg_read_cnt = 0;
+                       pmhctl->log_parms.link_active_cnt = 0;
+                       pmhctl->log_parms.link_hibernate_cnt = 0;
+                       pmhctl->log_parms.fwd_crc_cnt = 0;
+                       pmhctl->log_parms.rev_crc_cnt = 0;
+                       pmhctl->log_parms.vsync_response_cnt = 0;
+
+                       prev_parms[host_idx] = pmhctl->log_parms;
+                       mddi_client_capability_pkt.packet_length = 0;
+               }
+
+#ifndef T_MSM7500
+               /* tell clock driver we are user of this PLL */
+               MDDI_HOST_ENABLE_IO_CLOCK;
+#endif
+       }
+
+       mddi_host_powerup(host_idx);
+       pmhctl = &(mhctl[host_idx]);
+}
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+static uint32 mddi_client_id;
+
+uint32 mddi_get_client_id(void)
+{
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+       mddi_host_type host_idx = MDDI_HOST_PRIM;
+       static boolean client_detection_try = FALSE;
+       mddi_host_cntl_type *pmhctl;
+       unsigned long flags;
+       uint16 saved_rev_pkt_size;
+
+       if (!client_detection_try) {
+               /* Toshiba display requires larger drive_lo value */
+               mddi_host_reg_out(DRIVE_LO, 0x0050);
+
+               pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+               saved_rev_pkt_size = pmhctl->rev_pkt_size;
+
+               /* Increase Rev Encap Size */
+               pmhctl->rev_pkt_size = MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE;
+               mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+
+               /* disable hibernation temporarily */
+               if (!pmhctl->disable_hibernation)
+                       mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+
+               mddi_rev_user.waiting = TRUE;
+               INIT_COMPLETION(mddi_rev_user.done_comp);
+
+               spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+               /* turn on clock(s), if they have been disabled */
+               mddi_host_enable_hclk();
+               mddi_host_enable_io_clock();
+
+               mddi_client_capability_request = TRUE;
+
+               if (pmhctl->rev_state == MDDI_REV_IDLE) {
+                       /* attempt to send the reverse encapsulation now */
+                       mddi_issue_reverse_encapsulation();
+               }
+               spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+               wait_for_completion_killable(&(mddi_rev_user.done_comp));
+
+               /* Set Rev Encap Size back to its original value */
+               pmhctl->rev_pkt_size = saved_rev_pkt_size;
+               mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+
+               /* reenable auto-hibernate */
+               if (!pmhctl->disable_hibernation)
+                       mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+
+               mddi_host_reg_out(DRIVE_LO, 0x0032);
+               client_detection_try = TRUE;
+
+               mddi_client_id = (mddi_client_capability_pkt.Mfr_Name<<16) |
+                               mddi_client_capability_pkt.Product_Code;
+
+               if (!mddi_client_id)
+                       mddi_disable(1);
+       }
+
+#if 0
+       switch (mddi_client_capability_pkt.Mfr_Name) {
+       case 0x4474:
+               if ((mddi_client_capability_pkt.Product_Code != 0x8960) &&
+                   (target == DISPLAY_1)) {
+                       ret = PRISM_WVGA;
+               }
+               break;
+
+       case 0xD263:
+               if (target == DISPLAY_1)
+                       ret = TOSHIBA_VGA_PRIM;
+               else if (target == DISPLAY_2)
+                       ret = TOSHIBA_QCIF_SECD;
+               break;
+
+       case 0:
+               if (mddi_client_capability_pkt.Product_Code == 0x8835) {
+                       if (target == DISPLAY_1)
+                               ret = SHARP_QVGA_PRIM;
+                       else if (target == DISPLAY_2)
+                               ret = SHARP_128x128_SECD;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       if ((!client_detection_try) && (ret != TOSHIBA_VGA_PRIM)
+           && (ret != TOSHIBA_QCIF_SECD)) {
+               /* Not a Toshiba display, so change drive_lo back to default value */
+               mddi_host_reg_out(DRIVE_LO, 0x0032);
+       }
+#endif
+
+#endif
+
+       return mddi_client_id;
+}
+#endif
+
+void mddi_host_powerdown(mddi_host_type host_idx)
+{
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       if (host_idx >= MDDI_NUM_HOST_CORES) {
+               MDDI_MSG_ERR("Invalid host core index\n");
+               return;
+       }
+
+       if (pmhctl->driver_state == MDDI_DRIVER_RESET) {
+               return;
+       }
+
+       if (host_idx == MDDI_HOST_PRIM) {
+               /* disable timer */
+               del_timer(&mddi_host_timer);
+       }
+
+       mddi_host_configure_interrupts(host_idx, FALSE);
+
+       /* turn on HCLK to MDDI host core if it has been disabled */
+       mddi_host_enable_hclk();
+
+       /* MDDI Reset command */
+       mddi_host_reg_out(CMD, MDDI_CMD_RESET);
+
+       /* Pad Control Register */
+       mddi_host_reg_out(PAD_CTL, 0x0);
+
+       /* disable IO_CLK and hclk to MDDI host core */
+       mddi_host_disable_io_clock();
+       mddi_host_disable_hclk();
+
+       pmhctl->link_state = MDDI_LINK_DISABLED;
+       pmhctl->driver_state = MDDI_DRIVER_RESET;
+
+       MDDI_MSG_NOTICE("MDDI Host: Disabling Link\n");
+
+}
+
+uint16 mddi_get_next_free_llist_item(mddi_host_type host_idx, boolean wait)
+{
+       unsigned long flags;
+       uint16 ret_idx;
+       boolean forced_wait = FALSE;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       ret_idx = pmhctl->llist_info.next_free_idx;
+
+       pmhctl->llist_info.next_free_idx++;
+       if (pmhctl->llist_info.next_free_idx >= MDDI_NUM_DYNAMIC_LLIST_ITEMS)
+               pmhctl->llist_info.next_free_idx = MDDI_FIRST_DYNAMIC_LLIST_IDX;
+       spin_lock_irqsave(&mddi_host_spin_lock, flags);
+       if (pmhctl->llist_notify[ret_idx].in_use) {
+               if (!wait) {
+                       pmhctl->llist_info.next_free_idx = ret_idx;
+                       ret_idx = UNASSIGNED_INDEX;
+               } else {
+                       forced_wait = TRUE;
+                       INIT_COMPLETION(pmhctl->mddi_llist_avail_comp);
+               }
+       }
+       spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+       if (forced_wait) {
+               wait_for_completion_killable(&
+                                                 (pmhctl->
+                                                  mddi_llist_avail_comp));
+               MDDI_MSG_ERR("task waiting on mddi llist item\n");
+       }
+
+       if (ret_idx != UNASSIGNED_INDEX) {
+               pmhctl->llist_notify[ret_idx].waiting = FALSE;
+               pmhctl->llist_notify[ret_idx].done_cb = NULL;
+               pmhctl->llist_notify[ret_idx].in_use = TRUE;
+               pmhctl->llist_notify[ret_idx].next_idx = UNASSIGNED_INDEX;
+       }
+
+       return ret_idx;
+}
+
+uint16 mddi_get_reg_read_llist_item(mddi_host_type host_idx, boolean wait)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+       MDDI_MSG_CRIT("No reverse link available\n");
+       (void)wait;
+       return FALSE;
+#else
+       unsigned long flags;
+       uint16 ret_idx;
+       boolean error = FALSE;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       spin_lock_irqsave(&mddi_host_spin_lock, flags);
+       if (pmhctl->llist_info.reg_read_idx != UNASSIGNED_INDEX) {
+               /* need to block here or is this an error condition? */
+               error = TRUE;
+               ret_idx = UNASSIGNED_INDEX;
+       }
+       spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+       if (!error) {
+               ret_idx = pmhctl->llist_info.reg_read_idx =
+                   mddi_get_next_free_llist_item(host_idx, wait);
+               /* clear the reg_read_waiting flag */
+               pmhctl->llist_info.reg_read_waiting = FALSE;
+       }
+
+       if (error)
+               MDDI_MSG_ERR("***** Reg read still in progress! ****\n");
+       return ret_idx;
+#endif
+
+}
+
+void mddi_queue_forward_packets(uint16 first_llist_idx,
+                               uint16 last_llist_idx,
+                               boolean wait,
+                               mddi_llist_done_cb_type llist_done_cb,
+                               mddi_host_type host_idx)
+{
+       unsigned long flags;
+       mddi_linked_list_type *llist;
+       mddi_linked_list_type *llist_dma;
+       mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+       if ((first_llist_idx >= UNASSIGNED_INDEX) ||
+           (last_llist_idx >= UNASSIGNED_INDEX)) {
+               MDDI_MSG_ERR("MDDI queueing invalid linked list\n");
+               return;
+       }
+
+       if (pmhctl->link_state == MDDI_LINK_DISABLED)
+               MDDI_MSG_CRIT("MDDI host powered down!\n");
+
+       llist = pmhctl->llist_ptr;
+       llist_dma = pmhctl->llist_dma_ptr;
+
+       /* clean cache so MDDI host can read data */
+       memory_barrier();
+
+       pmhctl->llist_notify[last_llist_idx].waiting = wait;
+       if (wait)
+               INIT_COMPLETION(pmhctl->llist_notify[last_llist_idx].done_comp);
+       pmhctl->llist_notify[last_llist_idx].done_cb = llist_done_cb;
+
+       spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+       if ((pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+           (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
+           (pmhctl->rev_state == MDDI_REV_IDLE)) {
+               /* no packets are currently transmitting */
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+               if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+                       /* This is the special case where the packet is a register read. */
+                       pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
+                       mddi_reg_read_retry = 0;
+                       /* mddi_rev_reg_read_attempt = 1; */
+               }
+#endif
+               /* assign transmitting index values */
+               pmhctl->llist_info.transmitting_start_idx = first_llist_idx;
+               pmhctl->llist_info.transmitting_end_idx = last_llist_idx;
+
+               /* turn on clock(s), if they have been disabled */
+               mddi_host_enable_hclk();
+               mddi_host_enable_io_clock();
+               pmhctl->int_type.llist_ptr_write_1++;
+               /* Write to primary pointer register */
+               dma_coherent_pre_ops();
+               mddi_host_reg_out(PRI_PTR, &llist_dma[first_llist_idx]);
+
+               /* enable interrupt when complete */
+               mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
+                                  MDDI_INT_PRI_LINK_LIST_DONE);
+
+       } else if (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) {
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+               if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+                       /*
+                        * we have a register read to send but need to wait
+                        * for current reverse activity to end or there are
+                        * packets currently transmitting
+                        */
+                       /* mddi_rev_reg_read_attempt = 0; */
+                       pmhctl->llist_info.reg_read_waiting = TRUE;
+               }
+#endif
+
+               /* assign waiting index values */
+               pmhctl->llist_info.waiting_start_idx = first_llist_idx;
+               pmhctl->llist_info.waiting_end_idx = last_llist_idx;
+       } else {
+               uint16 prev_end_idx = pmhctl->llist_info.waiting_end_idx;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+               if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+                       /*
+                        * we have a register read to send but need to wait
+                        * for current reverse activity to end or there are
+                        * packets currently transmitting
+                        */
+                       /* mddi_rev_reg_read_attempt = 0; */
+                       pmhctl->llist_info.reg_read_waiting = TRUE;
+               }
+#endif
+
+               llist = pmhctl->llist_ptr;
+
+               /* clear end flag in previous last packet */
+               llist[prev_end_idx].link_controller_flags = 0;
+               pmhctl->llist_notify[prev_end_idx].next_idx = first_llist_idx;
+
+               /* set the next_packet_pointer of the previous last packet */
+               llist[prev_end_idx].next_packet_pointer =
+                   (void *)(&llist_dma[first_llist_idx]);
+
+               /* clean cache so MDDI host can read data */
+               memory_barrier();
+
+               /* assign new waiting last index value */
+               pmhctl->llist_info.waiting_end_idx = last_llist_idx;
+       }
+
+       spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+}
+
+void mddi_host_write_pix_attr_reg(uint32 value)
+{
+       (void)value;
+}
+
+void mddi_queue_reverse_encapsulation(boolean wait)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+       MDDI_MSG_CRIT("No reverse link available\n");
+       (void)wait;
+#else
+       unsigned long flags;
+       boolean error = FALSE;
+       mddi_host_type host_idx = MDDI_HOST_PRIM;
+       mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+       spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+       /* turn on clock(s), if they have been disabled */
+       mddi_host_enable_hclk();
+       mddi_host_enable_io_clock();
+
+       if (wait) {
+               if (!mddi_rev_user.waiting) {
+                       mddi_rev_user.waiting = TRUE;
+                       INIT_COMPLETION(mddi_rev_user.done_comp);
+               } else
+                       error = TRUE;
+       }
+       mddi_rev_encap_user_request = TRUE;
+
+       if (pmhctl->rev_state == MDDI_REV_IDLE) {
+               /* attempt to send the reverse encapsulation now */
+               mddi_host_type orig_host_idx = mddi_curr_host;
+               mddi_curr_host = host_idx;
+               mddi_issue_reverse_encapsulation();
+               mddi_curr_host = orig_host_idx;
+       }
+       spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+       if (error) {
+               MDDI_MSG_ERR("Reverse Encap request already in progress\n");
+       } else if (wait)
+               wait_for_completion_killable(&(mddi_rev_user.done_comp));
+#endif
+}
+
+/* ISR to be executed */
+boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+       MDDI_MSG_CRIT("No reverse link available\n");
+       (void)handler;
+       (void)pkt_type;
+       return (FALSE);
+#else
+       unsigned long flags;
+       uint16 hdlr;
+       boolean handler_set = FALSE;
+       boolean overwrite = FALSE;
+       mddi_host_type host_idx = MDDI_HOST_PRIM;
+       mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+       /* Disable interrupts */
+       spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+       for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
+               if (mddi_rev_pkt_handler[hdlr].pkt_type == pkt_type) {
+                       mddi_rev_pkt_handler[hdlr].handler = handler;
+                       if (handler == NULL) {
+                               /* clearing handler from table */
+                               mddi_rev_pkt_handler[hdlr].pkt_type =
+                                   INVALID_PKT_TYPE;
+                               handler_set = TRUE;
+                               if (pkt_type == 0x10) { /* video stream packet */
+                                       /* ensure HCLK on to MDDI host core before register write */
+                                       mddi_host_enable_hclk();
+                                       /* No longer getting video, so reset rev encap size to default */
+                                       pmhctl->rev_pkt_size =
+                                           MDDI_DEFAULT_REV_PKT_SIZE;
+                                       mddi_host_reg_out(REV_ENCAP_SZ,
+                                                         pmhctl->rev_pkt_size);
+                               }
+                       } else {
+                               /* already a handler for this packet */
+                               overwrite = TRUE;
+                       }
+                       break;
+               }
+       }
+       if ((hdlr >= MAX_MDDI_REV_HANDLERS) && (handler != NULL)) {
+               /* assigning new handler */
+               for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
+                       if (mddi_rev_pkt_handler[hdlr].pkt_type ==
+                           INVALID_PKT_TYPE) {
+                               if ((pkt_type == 0x10) &&       /* video stream packet */
+                                   (pmhctl->rev_pkt_size <
+                                    MDDI_VIDEO_REV_PKT_SIZE)) {
+                                       /* ensure HCLK on to MDDI host core before register write */
+                                       mddi_host_enable_hclk();
+                                       /* Increase Rev Encap Size */
+                                       pmhctl->rev_pkt_size =
+                                           MDDI_VIDEO_REV_PKT_SIZE;
+                                       mddi_host_reg_out(REV_ENCAP_SZ,
+                                                         pmhctl->rev_pkt_size);
+                               }
+                               mddi_rev_pkt_handler[hdlr].handler = handler;
+                               mddi_rev_pkt_handler[hdlr].pkt_type = pkt_type;
+                               handler_set = TRUE;
+                               break;
+                       }
+               }
+       }
+
+       /* Restore interrupts */
+       spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+       if (overwrite)
+               MDDI_MSG_ERR("Overwriting previous rev packet handler\n");
+
+       return handler_set;
+
+#endif
+}                              /* mddi_set_rev_handler */
+
+void mddi_host_disable_hibernation(boolean disable)
+{
+       mddi_host_type host_idx = MDDI_HOST_PRIM;
+       mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+       if (disable) {
+               pmhctl->disable_hibernation = TRUE;
+               /* hibernation will be turned off by isr next time it is entered */
+       } else {
+               if (pmhctl->disable_hibernation) {
+                       unsigned long flags;
+                       spin_lock_irqsave(&mddi_host_spin_lock, flags);
+                       if (!MDDI_HOST_IS_HCLK_ON)
+                               MDDI_HOST_ENABLE_HCLK;
+                       mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+                       spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+                       pmhctl->disable_hibernation = FALSE;
+               }
+       }
+}
+
+void mddi_mhctl_remove(mddi_host_type host_idx)
+{
+       mddi_host_cntl_type *pmhctl;
+
+       pmhctl = &(mhctl[host_idx]);
+
+       dma_free_coherent(NULL, MDDI_LLIST_POOL_SIZE, (void *)pmhctl->llist_ptr,
+                         pmhctl->llist_dma_addr);
+
+       dma_free_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
+                         (void *)pmhctl->rev_data_buf,
+                         pmhctl->rev_data_dma_addr);
+}
diff --git a/drivers/staging/msm/mddihosti.h b/drivers/staging/msm/mddihosti.h
new file mode 100644 (file)
index 0000000..7b26a42
--- /dev/null
@@ -0,0 +1,547 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDDIHOSTI_H
+#define MDDIHOSTI_H
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include <linux/clk.h>
+
+/* Register offsets in MDDI, applies to both msm_pmdh_base and
+ * (u32)msm_emdh_base. */
+#define MDDI_CMD               0x0000
+#define MDDI_VERSION                   0x0004
+#define MDDI_PRI_PTR           0x0008
+#define MDDI_BPS               0x0010
+#define MDDI_SPM               0x0014
+#define MDDI_INT               0x0018
+#define MDDI_INTEN             0x001c
+#define MDDI_REV_PTR           0x0020
+#define MDDI_REV_SIZE          0x0024
+#define MDDI_STAT              0x0028
+#define MDDI_REV_RATE_DIV      0x002c
+#define MDDI_REV_CRC_ERR       0x0030
+#define MDDI_TA1_LEN           0x0034
+#define MDDI_TA2_LEN           0x0038
+#define MDDI_TEST              0x0040
+#define MDDI_REV_PKT_CNT       0x0044
+#define MDDI_DRIVE_HI          0x0048
+#define MDDI_DRIVE_LO          0x004c
+#define MDDI_DISP_WAKE         0x0050
+#define MDDI_REV_ENCAP_SZ      0x0054
+#define MDDI_RTD_VAL           0x0058
+#define MDDI_PAD_CTL           0x0068
+#define MDDI_DRIVER_START_CNT  0x006c
+#define MDDI_CORE_VER          0x008c
+#define MDDI_FIFO_ALLOC         0x0090
+#define MDDI_PAD_IO_CTL         0x00a0
+#define MDDI_PAD_CAL            0x00a4
+
+extern u32 mddi_msg_level;
+
+/* No longer need to write to clear these registers */
+#define xxxx_mddi_host_reg_outm(reg, mask, val)  \
+do { \
+       if (host_idx == MDDI_HOST_PRIM) \
+               mddi_host_reg_outm_pmdh(reg, mask, val); \
+       else \
+               mddi_host_reg_outm_emdh(reg, mask, val); \
+} while (0)
+
+#define mddi_host_reg_outm(reg, mask, val) \
+do { \
+       unsigned long __addr; \
+       if (host_idx == MDDI_HOST_PRIM) \
+               __addr = (u32)msm_pmdh_base + MDDI_##reg; \
+       else \
+               __addr = (u32)msm_emdh_base + MDDI_##reg; \
+       writel((readl(__addr) & ~(mask)) | ((val) & (mask)), __addr); \
+} while (0)
+
+#define xxxx_mddi_host_reg_out(reg, val) \
+do { \
+       if (host_idx == MDDI_HOST_PRIM)  \
+               mddi_host_reg_out_pmdh(reg, val); \
+       else \
+               mddi_host_reg_out_emdh(reg, val); \
+       } while (0)
+
+#define mddi_host_reg_out(reg, val) \
+do { \
+       if (host_idx == MDDI_HOST_PRIM) \
+               writel(val, (u32)msm_pmdh_base + MDDI_##reg); \
+       else \
+               writel(val, (u32)msm_emdh_base + MDDI_##reg); \
+} while (0)
+
+#define xxxx_mddi_host_reg_in(reg)  \
+  ((host_idx) ? \
+     mddi_host_reg_in_emdh(reg) : mddi_host_reg_in_pmdh(reg));
+
+#define mddi_host_reg_in(reg) \
+((host_idx) ? \
+       readl((u32)msm_emdh_base + MDDI_##reg) : \
+       readl((u32)msm_pmdh_base + MDDI_##reg)) \
+
+#define xxxx_mddi_host_reg_inm(reg, mask)  \
+  ((host_idx) ? \
+    mddi_host_reg_inm_emdh(reg, mask) : \
+    mddi_host_reg_inm_pmdh(reg, mask);)
+
+#define mddi_host_reg_inm(reg, mask) \
+((host_idx) ? \
+       readl((u32)msm_emdh_base + MDDI_##reg) & (mask) : \
+       readl((u32)msm_pmdh_base + MDDI_##reg) & (mask)) \
+
+/* Using non-cacheable pmem, so do nothing */
+#define mddi_invalidate_cache_lines(addr_start, num_bytes)
+/*
+ * Using non-cacheable pmem, so do nothing with cache
+ * but, ensure write goes out to memory
+ */
+#define mddi_flush_cache_lines(addr_start, num_bytes)  \
+    (void) addr_start; \
+    (void) num_bytes;  \
+    memory_barrier()
+
+/* Since this translates to Remote Procedure Calls to check on clock status
+* just use a local variable to keep track of io_clock */
+#define MDDI_HOST_IS_IO_CLOCK_ON mddi_host_io_clock_on
+#define MDDI_HOST_ENABLE_IO_CLOCK
+#define MDDI_HOST_DISABLE_IO_CLOCK
+#define MDDI_HOST_IS_HCLK_ON mddi_host_hclk_on
+#define MDDI_HOST_ENABLE_HCLK
+#define MDDI_HOST_DISABLE_HCLK
+#define FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
+#define FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
+
+#define TRAMP_MDDI_HOST_ISR TRAMP_MDDI_PRI_ISR
+#define TRAMP_MDDI_HOST_EXT_ISR TRAMP_MDDI_EXT_ISR
+#define MDP_LINE_COUNT_BMSK  0x3ff
+#define MDP_SYNC_STATUS  0x000c
+#define MDP_LINE_COUNT      \
+(readl(msm_mdp_base + MDP_SYNC_STATUS) & MDP_LINE_COUNT_BMSK)
+
+/* MDP sends 256 pixel packets, so lower value hibernates more without
+* significantly increasing latency of waiting for next subframe */
+#define MDDI_HOST_BYTES_PER_SUBFRAME  0x3C00
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+#define MDDI_HOST_TA2_LEN       0x001a
+#define MDDI_HOST_REV_RATE_DIV  0x0004
+#else
+#define MDDI_HOST_TA2_LEN       0x000c
+#define MDDI_HOST_REV_RATE_DIV  0x0002
+#endif
+
+#define MDDI_MSG_EMERG(msg, ...)    \
+       if (mddi_msg_level > 0)  \
+               printk(KERN_EMERG msg, ## __VA_ARGS__);
+#define MDDI_MSG_ALERT(msg, ...)    \
+       if (mddi_msg_level > 1)  \
+               printk(KERN_ALERT msg, ## __VA_ARGS__);
+#define MDDI_MSG_CRIT(msg, ...)    \
+       if (mddi_msg_level > 2)  \
+               printk(KERN_CRIT msg, ## __VA_ARGS__);
+#define MDDI_MSG_ERR(msg, ...)    \
+       if (mddi_msg_level > 3)  \
+               printk(KERN_ERR msg, ## __VA_ARGS__);
+#define MDDI_MSG_WARNING(msg, ...)    \
+       if (mddi_msg_level > 4)  \
+               printk(KERN_WARNING msg, ## __VA_ARGS__);
+#define MDDI_MSG_NOTICE(msg, ...)    \
+       if (mddi_msg_level > 5)  \
+               printk(KERN_NOTICE msg, ## __VA_ARGS__);
+#define MDDI_MSG_INFO(msg, ...)    \
+       if (mddi_msg_level > 6)  \
+               printk(KERN_INFO msg, ## __VA_ARGS__);
+#define MDDI_MSG_DEBUG(msg, ...)    \
+       if (mddi_msg_level > 7)  \
+               printk(KERN_DEBUG msg, ## __VA_ARGS__);
+
+#define GCC_PACKED __attribute__((packed))
+typedef struct GCC_PACKED {
+       uint16 packet_length;
+       /* total # of bytes in the packet not including
+               the packet_length field. */
+
+       uint16 packet_type;
+       /* A Packet Type of 70 identifies the packet as
+               a Client status Packet. */
+
+       uint16 bClient_ID;
+       /* This field is reserved for future use and shall
+               be set to zero. */
+
+} mddi_rev_packet_type;
+
+typedef struct GCC_PACKED {
+       uint16 packet_length;
+       /* total # of bytes in the packet not including
+               the packet_length field. */
+
+       uint16 packet_type;
+       /* A Packet Type of 70 identifies the packet as
+               a Client status Packet. */
+
+       uint16 bClient_ID;
+       /* This field is reserved for future use and shall
+               be set to zero. */
+
+       uint16 reverse_link_request;
+       /* 16 bit unsigned integer with number of bytes client
+               needs in the * reverse encapsulation message
+               to transmit data. */
+
+       uint8 crc_error_count;
+       uint8 capability_change;
+       uint16 graphics_busy_flags;
+
+       uint16 parameter_CRC;
+       /* 16-bit CRC of all the bytes in the packet
+               including Packet Length. */
+
+} mddi_client_status_type;
+
+typedef struct GCC_PACKED {
+       uint16 packet_length;
+       /* total # of bytes in the packet not including
+               the packet_length field. */
+
+       uint16 packet_type;
+       /* A Packet Type of 66 identifies the packet as
+               a Client Capability Packet. */
+
+       uint16 bClient_ID;
+       /* This field is reserved for future use and
+               shall be set to zero. */
+
+       uint16 Protocol_Version;
+       uint16 Minimum_Protocol_Version;
+       uint16 Data_Rate_Capability;
+       uint8 Interface_Type_Capability;
+       uint8 Number_of_Alt_Displays;
+       uint16 PostCal_Data_Rate;
+       uint16 Bitmap_Width;
+       uint16 Bitmap_Height;
+       uint16 Display_Window_Width;
+       uint16 Display_Window_Height;
+       uint32 Color_Map_Size;
+       uint16 Color_Map_RGB_Width;
+       uint16 RGB_Capability;
+       uint8 Monochrome_Capability;
+       uint8 Reserved_1;
+       uint16 Y_Cb_Cr_Capability;
+       uint16 Bayer_Capability;
+       uint16 Alpha_Cursor_Image_Planes;
+       uint32 Client_Feature_Capability_Indicators;
+       uint8 Maximum_Video_Frame_Rate_Capability;
+       uint8 Minimum_Video_Frame_Rate_Capability;
+       uint16 Minimum_Sub_frame_Rate;
+       uint16 Audio_Buffer_Depth;
+       uint16 Audio_Channel_Capability;
+       uint16 Audio_Sample_Rate_Capability;
+       uint8 Audio_Sample_Resolution;
+       uint8 Mic_Audio_Sample_Resolution;
+       uint16 Mic_Sample_Rate_Capability;
+       uint8 Keyboard_Data_Format;
+       uint8 pointing_device_data_format;
+       uint16 content_protection_type;
+       uint16 Mfr_Name;
+       uint16 Product_Code;
+       uint16 Reserved_3;
+       uint32 Serial_Number;
+       uint8 Week_of_Manufacture;
+       uint8 Year_of_Manufacture;
+
+       uint16 parameter_CRC;
+       /* 16-bit CRC of all the bytes in the packet including Packet Length. */
+
+} mddi_client_capability_type;
+
+typedef struct GCC_PACKED {
+       uint16 packet_length;
+       /* total # of bytes in the packet not including the packet_length field. */
+
+       uint16 packet_type;
+       /* A Packet Type of 16 identifies the packet as a Video Stream Packet. */
+
+       uint16 bClient_ID;
+       /* This field is reserved for future use and shall be set to zero. */
+
+       uint16 video_data_format_descriptor;
+       /* format of each pixel in the Pixel Data in the present stream in the
+        * present packet.
+        * If bits [15:13] = 000 monochrome
+        * If bits [15:13] = 001 color pixels (palette).
+        * If bits [15:13] = 010 color pixels in raw RGB
+        * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format
+        * If bits [15:13] = 100 Bayer pixels
+        */
+
+       uint16 pixel_data_attributes;
+       /* interpreted as follows:
+        * Bits [1:0] = 11  pixel data is displayed to both eyes
+        * Bits [1:0] = 10  pixel data is routed to the left eye only.
+        * Bits [1:0] = 01  pixel data is routed to the right eye only.
+        * Bits [1:0] = 00  pixel data is routed to the alternate display.
+        * Bit 2 is 0  Pixel Data is in the standard progressive format.
+        * Bit 2 is 1  Pixel Data is in interlace format.
+        * Bit 3 is 0  Pixel Data is in the standard progressive format.
+        * Bit 3 is 1  Pixel Data is in alternate pixel format.
+        * Bit 4 is 0  Pixel Data is to or from the display frame buffer.
+        * Bit 4 is 1  Pixel Data is to or from the camera.
+        * Bit 5 is 0  pixel data contains the next consecutive row of pixels.
+        * Bit 5 is 1  X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge,
+        *             X Start, and Y Start parameters are not defined and
+        *             shall be ignored by the client.
+        * Bits [7:6] = 01  Pixel data is written to the offline image buffer.
+        * Bits [7:6] = 00  Pixel data is written to the buffer to refresh display.
+        * Bits [7:6] = 11  Pixel data is written to all image buffers.
+        * Bits [7:6] = 10  Invalid. Reserved for future use.
+        * Bits 8 through 11 alternate display number.
+        * Bits 12 through 14 are reserved for future use and shall be set to zero.
+        * Bit 15 is 1 the row of pixels is the last row of pixels in a frame.
+        */
+
+       uint16 x_left_edge;
+       uint16 y_top_edge;
+       /* X,Y coordinate of the top left edge of the screen window */
+
+       uint16 x_right_edge;
+       uint16 y_bottom_edge;
+       /*  X,Y coordinate of the bottom right edge of the window being updated. */
+
+       uint16 x_start;
+       uint16 y_start;
+       /*  (X Start, Y Start) is the first pixel in the Pixel Data field below. */
+
+       uint16 pixel_count;
+       /*  number of pixels in the Pixel Data field below. */
+
+       uint16 parameter_CRC;
+       /*  16-bit CRC of all bytes from the Packet Length to the Pixel Count. */
+
+       uint16 reserved;
+       /* 16-bit variable to make structure align on 4 byte boundary */
+
+} mddi_video_stream_packet_type;
+
+typedef struct GCC_PACKED {
+       uint16 packet_length;
+       /* total # of bytes in the packet not including the packet_length field. */
+
+       uint16 packet_type;
+       /* A Packet Type of 146 identifies the packet as a Register Access Packet. */
+
+       uint16 bClient_ID;
+       /* This field is reserved for future use and shall be set to zero. */
+
+       uint16 read_write_info;
+       /* Bits 13:0  a 14-bit unsigned integer that specifies the number of
+        *            32-bit Register Data List items to be transferred in the
+        *            Register Data List field.
+        * Bits[15:14] = 00  Write to register(s);
+        * Bits[15:14] = 10  Read from register(s);
+        * Bits[15:14] = 11  Response to a Read.
+        * Bits[15:14] = 01  this value is reserved for future use. */
+
+       uint32 register_address;
+       /* the register address that is to be written to or read from. */
+
+       uint16 parameter_CRC;
+       /* 16-bit CRC of all bytes from the Packet Length to the Register Address. */
+
+       uint32 register_data_list;
+       /* list of 4-byte register data values for/from client registers */
+
+} mddi_register_access_packet_type;
+
+typedef union GCC_PACKED {
+       mddi_video_stream_packet_type video_pkt;
+       mddi_register_access_packet_type register_pkt;
+       /* add 48 byte pad to ensure 64 byte llist struct, that can be
+        * manipulated easily with cache */
+       uint32 alignment_pad[12];       /* 48 bytes */
+} mddi_packet_header_type;
+
+typedef struct GCC_PACKED mddi_host_llist_struct {
+       uint16 link_controller_flags;
+       uint16 packet_header_count;
+       uint16 packet_data_count;
+       void *packet_data_pointer;
+       struct mddi_host_llist_struct *next_packet_pointer;
+       uint16 reserved;
+       mddi_packet_header_type packet_header;
+} mddi_linked_list_type;
+
+typedef struct {
+       struct completion done_comp;
+       mddi_llist_done_cb_type done_cb;
+       uint16 next_idx;
+       boolean waiting;
+       boolean in_use;
+} mddi_linked_list_notify_type;
+
+#define MDDI_LLIST_POOL_SIZE 0x1000
+#define MDDI_MAX_NUM_LLIST_ITEMS (MDDI_LLIST_POOL_SIZE / \
+                sizeof(mddi_linked_list_type))
+#define UNASSIGNED_INDEX MDDI_MAX_NUM_LLIST_ITEMS
+#define MDDI_FIRST_DYNAMIC_LLIST_IDX 0
+
+/* Static llist items can be used for applications that frequently send
+ * the same set of packets using the linked list interface. */
+/* Here we configure for 6 static linked list items:
+ *  The 1st is used for a the adaptive backlight setting.
+ *  and the remaining 5 are used for sending window adjustments for
+ *  MDDI clients that need windowing info sent separate from video
+ *  packets. */
+#define MDDI_NUM_STATIC_ABL_ITEMS 1
+#define MDDI_NUM_STATIC_WINDOW_ITEMS 5
+#define MDDI_NUM_STATIC_LLIST_ITEMS (MDDI_NUM_STATIC_ABL_ITEMS + \
+                               MDDI_NUM_STATIC_WINDOW_ITEMS)
+#define MDDI_NUM_DYNAMIC_LLIST_ITEMS (MDDI_MAX_NUM_LLIST_ITEMS - \
+                               MDDI_NUM_STATIC_LLIST_ITEMS)
+
+#define MDDI_FIRST_STATIC_LLIST_IDX  MDDI_NUM_DYNAMIC_LLIST_ITEMS
+#define MDDI_FIRST_STATIC_ABL_IDX  MDDI_FIRST_STATIC_LLIST_IDX
+#define MDDI_FIRST_STATIC_WINDOW_IDX  (MDDI_FIRST_STATIC_LLIST_IDX + \
+                               MDDI_NUM_STATIC_ABL_ITEMS)
+
+/* GPIO registers */
+#define VSYNC_WAKEUP_REG          0x80
+#define GPIO_REG                  0x81
+#define GPIO_OUTPUT_REG           0x82
+#define GPIO_INTERRUPT_REG        0x83
+#define GPIO_INTERRUPT_ENABLE_REG 0x84
+#define GPIO_POLARITY_REG         0x85
+
+/* Interrupt Bits */
+#define MDDI_INT_PRI_PTR_READ       0x0001
+#define MDDI_INT_SEC_PTR_READ       0x0002
+#define MDDI_INT_REV_DATA_AVAIL     0x0004
+#define MDDI_INT_DISP_REQ           0x0008
+#define MDDI_INT_PRI_UNDERFLOW      0x0010
+#define MDDI_INT_SEC_UNDERFLOW      0x0020
+#define MDDI_INT_REV_OVERFLOW       0x0040
+#define MDDI_INT_CRC_ERROR          0x0080
+#define MDDI_INT_MDDI_IN            0x0100
+#define MDDI_INT_PRI_OVERWRITE      0x0200
+#define MDDI_INT_SEC_OVERWRITE      0x0400
+#define MDDI_INT_REV_OVERWRITE      0x0800
+#define MDDI_INT_DMA_FAILURE        0x1000
+#define MDDI_INT_LINK_ACTIVE        0x2000
+#define MDDI_INT_IN_HIBERNATION     0x4000
+#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000
+#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000
+#define MDDI_INT_NO_CMD_PKTS_PEND   0x20000
+#define MDDI_INT_RTD_FAILURE        0x40000
+
+#define MDDI_INT_ERROR_CONDITIONS ( \
+       MDDI_INT_PRI_UNDERFLOW | MDDI_INT_SEC_UNDERFLOW | \
+       MDDI_INT_REV_OVERFLOW | MDDI_INT_CRC_ERROR | \
+       MDDI_INT_PRI_OVERWRITE | MDDI_INT_SEC_OVERWRITE | \
+       MDDI_INT_RTD_FAILURE | \
+       MDDI_INT_REV_OVERWRITE | MDDI_INT_DMA_FAILURE)
+
+#define MDDI_INT_LINK_STATE_CHANGES ( \
+       MDDI_INT_LINK_ACTIVE | MDDI_INT_IN_HIBERNATION)
+
+/* Status Bits */
+#define MDDI_STAT_LINK_ACTIVE        0x0001
+#define MDDI_STAT_NEW_REV_PTR        0x0002
+#define MDDI_STAT_NEW_PRI_PTR        0x0004
+#define MDDI_STAT_NEW_SEC_PTR        0x0008
+#define MDDI_STAT_IN_HIBERNATION     0x0010
+#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020
+#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040
+#define MDDI_STAT_PENDING_TIMING_PKT 0x0080
+#define MDDI_STAT_PENDING_REV_ENCAP  0x0100
+#define MDDI_STAT_PENDING_POWERDOWN  0x0200
+#define MDDI_STAT_RTD_MEAS_FAIL      0x0800
+#define MDDI_STAT_CLIENT_WAKEUP_REQ  0x1000
+
+/* Command Bits */
+#define MDDI_CMD_POWERDOWN           0x0100
+#define MDDI_CMD_POWERUP             0x0200
+#define MDDI_CMD_HIBERNATE           0x0300
+#define MDDI_CMD_RESET               0x0400
+#define MDDI_CMD_DISP_IGNORE         0x0501
+#define MDDI_CMD_DISP_LISTEN         0x0500
+#define MDDI_CMD_SEND_REV_ENCAP      0x0600
+#define MDDI_CMD_GET_CLIENT_CAP      0x0601
+#define MDDI_CMD_GET_CLIENT_STATUS   0x0602
+#define MDDI_CMD_SEND_RTD            0x0700
+#define MDDI_CMD_LINK_ACTIVE         0x0900
+#define MDDI_CMD_PERIODIC_REV_ENCAP  0x0A00
+
+extern void mddi_host_init(mddi_host_type host);
+extern void mddi_host_powerdown(mddi_host_type host);
+extern uint16 mddi_get_next_free_llist_item(mddi_host_type host, boolean wait);
+extern uint16 mddi_get_reg_read_llist_item(mddi_host_type host, boolean wait);
+extern void mddi_queue_forward_packets(uint16 first_llist_idx,
+                                      uint16 last_llist_idx,
+                                      boolean wait,
+                                      mddi_llist_done_cb_type llist_done_cb,
+                                      mddi_host_type host);
+
+extern void mddi_host_write_pix_attr_reg(uint32 value);
+extern void mddi_client_lcd_gpio_poll(uint32 poll_reg_val);
+extern void mddi_client_lcd_vsync_detected(boolean detected);
+extern void mddi_host_disable_hibernation(boolean disable);
+
+extern mddi_linked_list_type *llist_extern[];
+extern mddi_linked_list_type *llist_dma_extern[];
+extern mddi_linked_list_notify_type *llist_extern_notify[];
+extern struct timer_list mddi_host_timer;
+
+typedef struct {
+       uint16 transmitting_start_idx;
+       uint16 transmitting_end_idx;
+       uint16 waiting_start_idx;
+       uint16 waiting_end_idx;
+       uint16 reg_read_idx;
+       uint16 next_free_idx;
+       boolean reg_read_waiting;
+} mddi_llist_info_type;
+
+extern mddi_llist_info_type mddi_llist;
+
+#define MDDI_GPIO_DEFAULT_POLLING_INTERVAL 200
+typedef struct {
+       uint32 polling_reg;
+       uint32 polling_val;
+       uint32 polling_interval;
+       boolean polling_enabled;
+} mddi_gpio_info_type;
+
+uint32 mddi_get_client_id(void);
+void mddi_mhctl_remove(mddi_host_type host_idx);
+void mddi_host_timer_service(unsigned long data);
+#endif /* MDDIHOSTI_H */
diff --git a/drivers/staging/msm/mdp.c b/drivers/staging/msm/mdp.c
new file mode 100644 (file)
index 0000000..36053af
--- /dev/null
@@ -0,0 +1,1113 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#ifdef CONFIG_FB_MSM_MDP40
+#include "mdp4.h"
+#endif
+
+static struct clk *mdp_clk;
+static struct clk *mdp_pclk;
+
+struct completion mdp_ppp_comp;
+struct semaphore mdp_ppp_mutex;
+struct semaphore mdp_pipe_ctrl_mutex;
+
+unsigned long mdp_timer_duration = (HZ);   /* 1 sec */
+/* unsigned long mdp_mdp_timer_duration=0; */
+
+boolean mdp_ppp_waiting = FALSE;
+uint32 mdp_tv_underflow_cnt;
+uint32 mdp_lcdc_underflow_cnt;
+
+boolean mdp_current_clk_on = FALSE;
+boolean mdp_is_in_isr = FALSE;
+
+/*
+ * legacy mdp_in_processing is only for DMA2-MDDI
+ * this applies to DMA2 block only
+ */
+uint32 mdp_in_processing = FALSE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+uint32 mdp_intr_mask = MDP4_ANY_INTR_MASK;
+#else
+uint32 mdp_intr_mask = MDP_ANY_INTR_MASK;
+#endif
+
+MDP_BLOCK_TYPE mdp_debug[MDP_MAX_BLOCK];
+
+int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
+
+spinlock_t mdp_spin_lock;
+struct workqueue_struct *mdp_dma_wq;   /*mdp dma wq */
+struct workqueue_struct *mdp_vsync_wq; /*mdp vsync wq */
+
+static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */
+static struct delayed_work mdp_pipe_ctrl_worker;
+
+#ifdef CONFIG_FB_MSM_MDP40
+struct mdp_dma_data dma2_data;
+struct mdp_dma_data dma_s_data;
+struct mdp_dma_data dma_e_data;
+#else
+static struct mdp_dma_data dma2_data;
+static struct mdp_dma_data dma_s_data;
+static struct mdp_dma_data dma_e_data;
+#endif
+static struct mdp_dma_data dma3_data;
+
+extern ktime_t mdp_dma2_last_update_time;
+
+extern uint32 mdp_dma2_update_time_in_usec;
+extern int mdp_lcd_rd_cnt_offset_slow;
+extern int mdp_lcd_rd_cnt_offset_fast;
+extern int mdp_usec_diff_threshold;
+
+#ifdef CONFIG_FB_MSM_LCDC
+extern int mdp_lcdc_pclk_clk_rate;
+extern int mdp_lcdc_pad_pclk_clk_rate;
+extern int first_pixel_start_x;
+extern int first_pixel_start_y;
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+struct dentry *mdp_dir;
+#endif
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int mdp_suspend(struct platform_device *pdev, pm_message_t state);
+#else
+#define mdp_suspend NULL
+#endif
+
+struct timeval mdp_dma2_timeval;
+struct timeval mdp_ppp_timeval;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static struct early_suspend early_suspend;
+#endif
+
+#ifndef CONFIG_FB_MSM_MDP22
+DEFINE_MUTEX(mdp_lut_push_sem);
+static int mdp_lut_i;
+static int mdp_lut_hw_update(struct fb_cmap *cmap)
+{
+       int i;
+       u16 *c[3];
+       u16 r, g, b;
+
+       c[0] = cmap->green;
+       c[1] = cmap->blue;
+       c[2] = cmap->red;
+
+       for (i = 0; i < cmap->len; i++) {
+               if (copy_from_user(&r, cmap->red++, sizeof(r)) ||
+                   copy_from_user(&g, cmap->green++, sizeof(g)) ||
+                   copy_from_user(&b, cmap->blue++, sizeof(b)))
+                       return -EFAULT;
+
+#ifdef CONFIG_FB_MSM_MDP40
+               MDP_OUTP(MDP_BASE + 0x94800 +
+#else
+               MDP_OUTP(MDP_BASE + 0x93800 +
+#endif
+                       (0x400*mdp_lut_i) + cmap->start*4 + i*4,
+                               ((g & 0xff) |
+                                ((b & 0xff) << 8) |
+                                ((r & 0xff) << 16)));
+       }
+
+       return 0;
+}
+
+static int mdp_lut_push;
+static int mdp_lut_push_i;
+static int mdp_lut_update_nonlcdc(struct fb_info *info, struct fb_cmap *cmap)
+{
+       int ret;
+
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+       ret = mdp_lut_hw_update(cmap);
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+       if (ret)
+               return ret;
+
+       mutex_lock(&mdp_lut_push_sem);
+       mdp_lut_push = 1;
+       mdp_lut_push_i = mdp_lut_i;
+       mutex_unlock(&mdp_lut_push_sem);
+
+       mdp_lut_i = (mdp_lut_i + 1)%2;
+
+       return 0;
+}
+
+static int mdp_lut_update_lcdc(struct fb_info *info, struct fb_cmap *cmap)
+{
+       int ret;
+
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+       ret = mdp_lut_hw_update(cmap);
+
+       if (ret) {
+               mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+               return ret;
+       }
+
+       MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | 0x17);
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+       mdp_lut_i = (mdp_lut_i + 1)%2;
+
+       return 0;
+}
+
+#define MDP_HIST_MAX_BIN 32
+static __u32 mdp_hist_r[MDP_HIST_MAX_BIN];
+static __u32 mdp_hist_g[MDP_HIST_MAX_BIN];
+static __u32 mdp_hist_b[MDP_HIST_MAX_BIN];
+
+#ifdef CONFIG_FB_MSM_MDP40
+struct mdp_histogram mdp_hist;
+struct completion mdp_hist_comp;
+#else
+static struct mdp_histogram mdp_hist;
+static struct completion mdp_hist_comp;
+#endif
+
+static int mdp_do_histogram(struct fb_info *info, struct mdp_histogram *hist)
+{
+       int ret = 0;
+
+       if (!hist->frame_cnt || (hist->bin_cnt == 0) ||
+                                (hist->bin_cnt > MDP_HIST_MAX_BIN))
+               return -EINVAL;
+
+       INIT_COMPLETION(mdp_hist_comp);
+
+       mdp_hist.bin_cnt = hist->bin_cnt;
+       mdp_hist.r = (hist->r) ? mdp_hist_r : 0;
+       mdp_hist.g = (hist->g) ? mdp_hist_g : 0;
+       mdp_hist.b = (hist->b) ? mdp_hist_b : 0;
+
+#ifdef CONFIG_FB_MSM_MDP40
+       MDP_OUTP(MDP_BASE + 0x95004, hist->frame_cnt);
+       MDP_OUTP(MDP_BASE + 0x95000, 1);
+#else
+       MDP_OUTP(MDP_BASE + 0x94004, hist->frame_cnt);
+       MDP_OUTP(MDP_BASE + 0x94000, 1);
+#endif
+       wait_for_completion_killable(&mdp_hist_comp);
+
+       if (hist->r) {
+               ret = copy_to_user(hist->r, mdp_hist.r, hist->bin_cnt*4);
+               if (ret)
+                       goto hist_err;
+       }
+       if (hist->g) {
+               ret = copy_to_user(hist->g, mdp_hist.g, hist->bin_cnt*4);
+               if (ret)
+                       goto hist_err;
+       }
+       if (hist->b) {
+               ret = copy_to_user(hist->b, mdp_hist.b, hist->bin_cnt*4);
+               if (ret)
+                       goto hist_err;
+       }
+       return 0;
+
+hist_err:
+       printk(KERN_ERR "%s: invalid hist buffer\n", __func__);
+       return ret;
+}
+#endif
+
+/* Returns < 0 on error, 0 on timeout, or > 0 on successful wait */
+
+int mdp_ppp_pipe_wait(void)
+{
+       int ret = 1;
+
+       /* wait 5 seconds for the operation to complete before declaring
+       the MDP hung */
+
+       if (mdp_ppp_waiting == TRUE) {
+               ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp,
+                                                               5 * HZ);
+
+               if (!ret)
+                       printk(KERN_ERR "%s: Timed out waiting for the MDP.\n",
+                                       __func__);
+       }
+
+       return ret;
+}
+
+static DEFINE_SPINLOCK(mdp_lock);
+static int mdp_irq_mask;
+static int mdp_irq_enabled;
+
+void mdp_enable_irq(uint32 term)
+{
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&mdp_lock, irq_flags);
+       if (mdp_irq_mask & term) {
+               printk(KERN_ERR "MDP IRQ term-0x%x is already set\n", term);
+       } else {
+               mdp_irq_mask |= term;
+               if (mdp_irq_mask && !mdp_irq_enabled) {
+                       mdp_irq_enabled = 1;
+                       enable_irq(INT_MDP);
+               }
+       }
+       spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
+void mdp_disable_irq(uint32 term)
+{
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&mdp_lock, irq_flags);
+       if (!(mdp_irq_mask & term)) {
+               printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term);
+       } else {
+               mdp_irq_mask &= ~term;
+               if (!mdp_irq_mask && mdp_irq_enabled) {
+                       mdp_irq_enabled = 0;
+                       disable_irq(INT_MDP);
+               }
+       }
+       spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
+void mdp_disable_irq_nolock(uint32 term)
+{
+
+       if (!(mdp_irq_mask & term)) {
+               printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term);
+       } else {
+               mdp_irq_mask &= ~term;
+               if (!mdp_irq_mask && mdp_irq_enabled) {
+                       mdp_irq_enabled = 0;
+                       disable_irq(INT_MDP);
+               }
+       }
+}
+
+void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
+{
+
+       dmb();  /* memory barrier */
+
+       /* kick off PPP engine */
+       if (term == MDP_PPP_TERM) {
+               if (mdp_debug[MDP_PPP_BLOCK])
+                       jiffies_to_timeval(jiffies, &mdp_ppp_timeval);
+
+               /* let's turn on PPP block */
+               mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+               mdp_enable_irq(term);
+               INIT_COMPLETION(mdp_ppp_comp);
+               mdp_ppp_waiting = TRUE;
+               outpdw(MDP_BASE + 0x30, 0x1000);
+               wait_for_completion_killable(&mdp_ppp_comp);
+               mdp_disable_irq(term);
+
+               if (mdp_debug[MDP_PPP_BLOCK]) {
+                       struct timeval now;
+
+                       jiffies_to_timeval(jiffies, &now);
+                       mdp_ppp_timeval.tv_usec =
+                           now.tv_usec - mdp_ppp_timeval.tv_usec;
+                       MSM_FB_INFO("MDP-PPP: %d\n",
+                                   (int)mdp_ppp_timeval.tv_usec);
+               }
+       } else if (term == MDP_DMA2_TERM) {
+               if (mdp_debug[MDP_DMA2_BLOCK]) {
+                       MSM_FB_INFO("MDP-DMA2: %d\n",
+                                   (int)mdp_dma2_timeval.tv_usec);
+                       jiffies_to_timeval(jiffies, &mdp_dma2_timeval);
+               }
+               /* DMA update timestamp */
+               mdp_dma2_last_update_time = ktime_get_real();
+               /* let's turn on DMA2 block */
+#if 0
+               mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+#endif
+#ifdef CONFIG_FB_MSM_MDP22
+               outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x0044, 0x0);/* start DMA */
+#else
+               if (mdp_lut_push) {
+                       mutex_lock(&mdp_lut_push_sem);
+                       mdp_lut_push = 0;
+                       MDP_OUTP(MDP_BASE + 0x90070,
+                                       (mdp_lut_push_i << 10) | 0x17);
+                       mutex_unlock(&mdp_lut_push_sem);
+               }
+#ifdef CONFIG_FB_MSM_MDP40
+               outpdw(MDP_BASE + 0x000c, 0x0); /* start DMA */
+#else
+               outpdw(MDP_BASE + 0x0044, 0x0); /* start DMA */
+#endif
+#endif
+#ifdef CONFIG_FB_MSM_MDP40
+       } else if (term == MDP_DMA_S_TERM) {
+               mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+               outpdw(MDP_BASE + 0x0010, 0x0); /* start DMA */
+       } else if (term == MDP_DMA_E_TERM) {
+               mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+               outpdw(MDP_BASE + 0x0014, 0x0); /* start DMA */
+       } else if (term == MDP_OVERLAY0_TERM) {
+               mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+               outpdw(MDP_BASE + 0x0004, 0);
+       } else if (term == MDP_OVERLAY1_TERM) {
+               mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+               outpdw(MDP_BASE + 0x0008, 0);
+       }
+#else
+       } else if (term == MDP_DMA_S_TERM) {
+               mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+               outpdw(MDP_BASE + 0x0048, 0x0); /* start DMA */
+       }
+#endif
+}
+
+static void mdp_pipe_ctrl_workqueue_handler(struct work_struct *work)
+{
+       mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+                  boolean isr)
+{
+       boolean mdp_all_blocks_off = TRUE;
+       int i;
+       unsigned long flag;
+
+       spin_lock_irqsave(&mdp_spin_lock, flag);
+       if (MDP_BLOCK_POWER_ON == state) {
+               mdp_block_power_cnt[block]++;
+
+               if (MDP_DMA2_BLOCK == block)
+                       mdp_in_processing = TRUE;
+       } else {
+               mdp_block_power_cnt[block]--;
+
+               if (mdp_block_power_cnt[block] < 0) {
+                       /*
+                       * Master has to serve a request to power off MDP always
+                       * It also has a timer to power off.  So, in case of
+                       * timer expires first and DMA2 finishes later,
+                       * master has to power off two times
+                       * There shouldn't be multiple power-off request for
+                       * other blocks
+                       */
+                       if (block != MDP_MASTER_BLOCK) {
+                               MSM_FB_INFO("mdp_block_power_cnt[block=%d] \
+                               multiple power-off request\n", block);
+                       }
+                       mdp_block_power_cnt[block] = 0;
+               }
+
+               if (MDP_DMA2_BLOCK == block)
+                       mdp_in_processing = FALSE;
+       }
+       spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+       /*
+        * If it's in isr, we send our request to workqueue.
+        * Otherwise, processing happens in the current context
+        */
+       if (isr) {
+               /* checking all blocks power state */
+               for (i = 0; i < MDP_MAX_BLOCK; i++) {
+                       if (mdp_block_power_cnt[i] > 0)
+                               mdp_all_blocks_off = FALSE;
+               }
+
+               if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
+                       /* send workqueue to turn off mdp power */
+                       queue_delayed_work(mdp_pipe_ctrl_wq,
+                                          &mdp_pipe_ctrl_worker,
+                                          mdp_timer_duration);
+               }
+       } else {
+               down(&mdp_pipe_ctrl_mutex);
+               /* checking all blocks power state */
+               for (i = 0; i < MDP_MAX_BLOCK; i++) {
+                       if (mdp_block_power_cnt[i] > 0)
+                               mdp_all_blocks_off = FALSE;
+               }
+
+               /*
+                * find out whether a delayable work item is currently
+                * pending
+                */
+
+               if (delayed_work_pending(&mdp_pipe_ctrl_worker)) {
+                       /*
+                        * try to cancel the current work if it fails to
+                        * stop (which means del_timer can't delete it
+                        * from the list, it's about to expire and run),
+                        * we have to let it run. queue_delayed_work won't
+                        * accept the next job which is same as
+                        * queue_delayed_work(mdp_timer_duration = 0)
+                        */
+                       cancel_delayed_work(&mdp_pipe_ctrl_worker);
+               }
+
+               if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
+                       if (block == MDP_MASTER_BLOCK) {
+                               mdp_current_clk_on = FALSE;
+                               /* turn off MDP clks */
+                               if (mdp_clk != NULL) {
+                                       clk_disable(mdp_clk);
+                                       MSM_FB_DEBUG("MDP CLK OFF\n");
+                               }
+                               if (mdp_pclk != NULL) {
+                                       clk_disable(mdp_pclk);
+                                       MSM_FB_DEBUG("MDP PCLK OFF\n");
+                               }
+                       } else {
+                               /* send workqueue to turn off mdp power */
+                               queue_delayed_work(mdp_pipe_ctrl_wq,
+                                                  &mdp_pipe_ctrl_worker,
+                                                  mdp_timer_duration);
+                       }
+               } else if ((!mdp_all_blocks_off) && (!mdp_current_clk_on)) {
+                       mdp_current_clk_on = TRUE;
+                       /* turn on MDP clks */
+                       if (mdp_clk != NULL) {
+                               clk_enable(mdp_clk);
+                               MSM_FB_DEBUG("MDP CLK ON\n");
+                       }
+                       if (mdp_pclk != NULL) {
+                               clk_enable(mdp_pclk);
+                               MSM_FB_DEBUG("MDP PCLK ON\n");
+                       }
+               }
+               up(&mdp_pipe_ctrl_mutex);
+       }
+}
+
+#ifndef CONFIG_FB_MSM_MDP40
+irqreturn_t mdp_isr(int irq, void *ptr)
+{
+       uint32 mdp_interrupt = 0;
+       struct mdp_dma_data *dma;
+
+       mdp_is_in_isr = TRUE;
+       do {
+               mdp_interrupt = inp32(MDP_INTR_STATUS);
+               outp32(MDP_INTR_CLEAR, mdp_interrupt);
+
+               mdp_interrupt &= mdp_intr_mask;
+
+               if (mdp_interrupt & TV_ENC_UNDERRUN) {
+                       mdp_interrupt &= ~(TV_ENC_UNDERRUN);
+                       mdp_tv_underflow_cnt++;
+               }
+
+               if (!mdp_interrupt)
+                       break;
+
+               /* DMA3 TV-Out Start */
+               if (mdp_interrupt & TV_OUT_DMA3_START) {
+                       /* let's disable TV out interrupt */
+                       mdp_intr_mask &= ~TV_OUT_DMA3_START;
+                       outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+                       dma = &dma3_data;
+                       if (dma->waiting) {
+                               dma->waiting = FALSE;
+                               complete(&dma->comp);
+                       }
+               }
+#ifndef CONFIG_FB_MSM_MDP22
+               if (mdp_interrupt & MDP_HIST_DONE) {
+                       outp32(MDP_BASE + 0x94018, 0x3);
+                       outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
+                       if (mdp_hist.r)
+                               memcpy(mdp_hist.r, MDP_BASE + 0x94100,
+                                               mdp_hist.bin_cnt*4);
+                       if (mdp_hist.g)
+                               memcpy(mdp_hist.g, MDP_BASE + 0x94200,
+                                               mdp_hist.bin_cnt*4);
+                       if (mdp_hist.b)
+                               memcpy(mdp_hist.b, MDP_BASE + 0x94300,
+                                               mdp_hist.bin_cnt*4);
+                       complete(&mdp_hist_comp);
+               }
+
+               /* LCDC UnderFlow */
+               if (mdp_interrupt & LCDC_UNDERFLOW) {
+                       mdp_lcdc_underflow_cnt++;
+               }
+               /* LCDC Frame Start */
+               if (mdp_interrupt & LCDC_FRAME_START) {
+                       /* let's disable LCDC interrupt */
+                       mdp_intr_mask &= ~LCDC_FRAME_START;
+                       outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+                       dma = &dma2_data;
+                       if (dma->waiting) {
+                               dma->waiting = FALSE;
+                               complete(&dma->comp);
+                       }
+               }
+
+               /* DMA2 LCD-Out Complete */
+               if (mdp_interrupt & MDP_DMA_S_DONE) {
+                       dma = &dma_s_data;
+                       dma->busy = FALSE;
+                       mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
+                                     TRUE);
+                       complete(&dma->comp);
+               }
+#endif
+
+               /* DMA2 LCD-Out Complete */
+               if (mdp_interrupt & MDP_DMA_P_DONE) {
+                       struct timeval now;
+                       ktime_t now_k;
+
+                       now_k = ktime_get_real();
+                       mdp_dma2_last_update_time.tv.sec =
+                           now_k.tv.sec - mdp_dma2_last_update_time.tv.sec;
+                       mdp_dma2_last_update_time.tv.nsec =
+                           now_k.tv.nsec - mdp_dma2_last_update_time.tv.nsec;
+
+                       if (mdp_debug[MDP_DMA2_BLOCK]) {
+                               jiffies_to_timeval(jiffies, &now);
+                               mdp_dma2_timeval.tv_usec =
+                                   now.tv_usec - mdp_dma2_timeval.tv_usec;
+                       }
+
+                       dma = &dma2_data;
+                       dma->busy = FALSE;
+                       mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
+                                     TRUE);
+                       complete(&dma->comp);
+               }
+               /* PPP Complete */
+               if (mdp_interrupt & MDP_PPP_DONE) {
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+                       mdp_ppp_djob_done();
+#else
+                       mdp_pipe_ctrl(MDP_PPP_BLOCK,
+                               MDP_BLOCK_POWER_OFF, TRUE);
+                       if (mdp_ppp_waiting) {
+                               mdp_ppp_waiting = FALSE;
+                               complete(&mdp_ppp_comp);
+                       }
+#endif
+               }
+       } while (1);
+
+       mdp_is_in_isr = FALSE;
+
+       return IRQ_HANDLED;
+}
+#endif
+
+static void mdp_drv_init(void)
+{
+       int i;
+
+       for (i = 0; i < MDP_MAX_BLOCK; i++) {
+               mdp_debug[i] = 0;
+       }
+
+       /* initialize spin lock and workqueue */
+       spin_lock_init(&mdp_spin_lock);
+       mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq");
+       mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq");
+       mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq");
+       INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker,
+                         mdp_pipe_ctrl_workqueue_handler);
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+       mdp_ppp_dq_init();
+#endif
+
+       /* initialize semaphore */
+       init_completion(&mdp_ppp_comp);
+       init_MUTEX(&mdp_ppp_mutex);
+       init_MUTEX(&mdp_pipe_ctrl_mutex);
+
+       dma2_data.busy = FALSE;
+       dma2_data.waiting = FALSE;
+       init_completion(&dma2_data.comp);
+       init_MUTEX(&dma2_data.mutex);
+       mutex_init(&dma2_data.ov_mutex);
+
+       dma3_data.busy = FALSE;
+       dma3_data.waiting = FALSE;
+       init_completion(&dma3_data.comp);
+       init_MUTEX(&dma3_data.mutex);
+
+       dma_s_data.busy = FALSE;
+       dma_s_data.waiting = FALSE;
+       init_completion(&dma_s_data.comp);
+       init_MUTEX(&dma_s_data.mutex);
+
+       dma_e_data.busy = FALSE;
+       dma_e_data.waiting = FALSE;
+       init_completion(&dma_e_data.comp);
+
+#ifndef CONFIG_FB_MSM_MDP22
+       init_completion(&mdp_hist_comp);
+#endif
+
+       /* initializing mdp power block counter to 0 */
+       for (i = 0; i < MDP_MAX_BLOCK; i++) {
+               mdp_block_power_cnt[i] = 0;
+       }
+
+#ifdef MSM_FB_ENABLE_DBGFS
+       {
+               struct dentry *root;
+               char sub_name[] = "mdp";
+
+               root = msm_fb_get_debugfs_root();
+               if (root != NULL) {
+                       mdp_dir = debugfs_create_dir(sub_name, root);
+
+                       if (mdp_dir) {
+                               msm_fb_debugfs_file_create(mdp_dir,
+                                       "dma2_update_time_in_usec",
+                                       (u32 *) &mdp_dma2_update_time_in_usec);
+                               msm_fb_debugfs_file_create(mdp_dir,
+                                       "vs_rdcnt_slow",
+                                       (u32 *) &mdp_lcd_rd_cnt_offset_slow);
+                               msm_fb_debugfs_file_create(mdp_dir,
+                                       "vs_rdcnt_fast",
+                                       (u32 *) &mdp_lcd_rd_cnt_offset_fast);
+                               msm_fb_debugfs_file_create(mdp_dir,
+                                       "mdp_usec_diff_threshold",
+                                       (u32 *) &mdp_usec_diff_threshold);
+                               msm_fb_debugfs_file_create(mdp_dir,
+                                       "mdp_current_clk_on",
+                                       (u32 *) &mdp_current_clk_on);
+#ifdef CONFIG_FB_MSM_LCDC
+                               msm_fb_debugfs_file_create(mdp_dir,
+                                       "lcdc_start_x",
+                                       (u32 *) &first_pixel_start_x);
+                               msm_fb_debugfs_file_create(mdp_dir,
+                                       "lcdc_start_y",
+                                       (u32 *) &first_pixel_start_y);
+                               msm_fb_debugfs_file_create(mdp_dir,
+                                       "mdp_lcdc_pclk_clk_rate",
+                                       (u32 *) &mdp_lcdc_pclk_clk_rate);
+                               msm_fb_debugfs_file_create(mdp_dir,
+                                       "mdp_lcdc_pad_pclk_clk_rate",
+                                       (u32 *) &mdp_lcdc_pad_pclk_clk_rate);
+#endif
+                       }
+               }
+       }
+#endif
+}
+
+static int mdp_probe(struct platform_device *pdev);
+static int mdp_remove(struct platform_device *pdev);
+
+static struct platform_driver mdp_driver = {
+       .probe = mdp_probe,
+       .remove = mdp_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+       .suspend = mdp_suspend,
+       .resume = NULL,
+#endif
+       .shutdown = NULL,
+       .driver = {
+               /*
+                * Driver name must match the device name added in
+                * platform.c.
+                */
+               .name = "mdp",
+       },
+};
+
+static int mdp_off(struct platform_device *pdev)
+{
+       int ret = 0;
+
+#ifdef MDP_HW_VSYNC
+       struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+#endif
+
+       ret = panel_next_off(pdev);
+
+#ifdef MDP_HW_VSYNC
+       mdp_hw_vsync_clk_disable(mfd);
+#endif
+
+       return ret;
+}
+
+static int mdp_on(struct platform_device *pdev)
+{
+#ifdef MDP_HW_VSYNC
+       struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+#endif
+
+       int ret = 0;
+
+#ifdef MDP_HW_VSYNC
+       mdp_hw_vsync_clk_enable(mfd);
+#endif
+
+       ret = panel_next_on(pdev);
+
+       return ret;
+}
+
+static int mdp_irq_clk_setup(void)
+{
+       int ret;
+
+#ifdef CONFIG_FB_MSM_MDP40
+       ret = request_irq(INT_MDP, mdp4_isr, IRQF_DISABLED, "MDP", 0);
+#else
+       ret = request_irq(INT_MDP, mdp_isr, IRQF_DISABLED, "MDP", 0);
+#endif
+       if (ret) {
+               printk(KERN_ERR "mdp request_irq() failed!\n");
+               return ret;
+       }
+       disable_irq(INT_MDP);
+
+       mdp_clk = clk_get(NULL, "mdp_clk");
+
+       if (IS_ERR(mdp_clk)) {
+               ret = PTR_ERR(mdp_clk);
+               printk(KERN_ERR "can't get mdp_clk error:%d!\n", ret);
+               free_irq(INT_MDP, 0);
+               return ret;
+       }
+
+       mdp_pclk = clk_get(NULL, "mdp_pclk");
+       if (IS_ERR(mdp_pclk))
+               mdp_pclk = NULL;
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+       /*
+        * mdp_clk should greater than mdp_pclk always
+        */
+       clk_set_rate(mdp_clk, 122880000); /* 122.88 Mhz */
+       printk(KERN_INFO "mdp_clk: mdp_clk=%d mdp_pclk=%d\n",
+               (int)clk_get_rate(mdp_clk), (int)clk_get_rate(mdp_pclk));
+#endif
+
+       return 0;
+}
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static int mdp_resource_initialized;
+static struct msm_panel_common_pdata *mdp_pdata;
+
+static int mdp_probe(struct platform_device *pdev)
+{
+       struct platform_device *msm_fb_dev = NULL;
+       struct msm_fb_data_type *mfd;
+       struct msm_fb_panel_data *pdata = NULL;
+       int rc;
+       resource_size_t  size ;
+#ifdef CONFIG_FB_MSM_MDP40
+       int intf, if_no;
+#else
+       unsigned long flag;
+#endif
+
+       if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+               mdp_pdata = pdev->dev.platform_data;
+
+               size =  resource_size(&pdev->resource[0]);
+               msm_mdp_base = ioremap(pdev->resource[0].start, size);
+
+               MSM_FB_INFO("MDP HW Base phy_Address = 0x%x virt = 0x%x\n",
+                       (int)pdev->resource[0].start, (int)msm_mdp_base);
+
+               if (unlikely(!msm_mdp_base))
+                       return -ENOMEM;
+
+               printk("irq clk setup\n");
+               rc = mdp_irq_clk_setup();
+               printk("irq clk setup done\n");
+               if (rc)
+                       return rc;
+
+               /* initializing mdp hw */
+#ifdef CONFIG_FB_MSM_MDP40
+               mdp4_hw_init();
+#else
+               mdp_hw_init();
+#endif
+
+               mdp_resource_initialized = 1;
+               return 0;
+       }
+
+       if (!mdp_resource_initialized)
+               return -EPERM;
+
+       mfd = platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+               return -ENOMEM;
+
+       msm_fb_dev = platform_device_alloc("msm_fb", pdev->id);
+       if (!msm_fb_dev)
+               return -ENOMEM;
+
+       /* link to the latest pdev */
+       mfd->pdev = msm_fb_dev;
+
+       /* add panel data */
+       if (platform_device_add_data
+           (msm_fb_dev, pdev->dev.platform_data,
+            sizeof(struct msm_fb_panel_data))) {
+               printk(KERN_ERR "mdp_probe: platform_device_add_data failed!\n");
+               rc = -ENOMEM;
+               goto mdp_probe_err;
+       }
+       /* data chain */
+       pdata = msm_fb_dev->dev.platform_data;
+       pdata->on = mdp_on;
+       pdata->off = mdp_off;
+       pdata->next = pdev;
+
+       switch (mfd->panel.type) {
+       case EXT_MDDI_PANEL:
+       case MDDI_PANEL:
+       case EBI2_PANEL:
+               INIT_WORK(&mfd->dma_update_worker,
+                         mdp_lcd_update_workqueue_handler);
+               INIT_WORK(&mfd->vsync_resync_worker,
+                         mdp_vsync_resync_workqueue_handler);
+               mfd->hw_refresh = FALSE;
+
+               if (mfd->panel.type == EXT_MDDI_PANEL) {
+                       /* 15 fps -> 66 msec */
+                       mfd->refresh_timer_duration = (66 * HZ / 1000);
+               } else {
+                       /* 24 fps -> 42 msec */
+                       mfd->refresh_timer_duration = (42 * HZ / 1000);
+               }
+
+#ifdef CONFIG_FB_MSM_MDP22
+               mfd->dma_fnc = mdp_dma2_update;
+               mfd->dma = &dma2_data;
+#else
+               if (mfd->panel_info.pdest == DISPLAY_1) {
+#ifdef CONFIG_FB_MSM_OVERLAY
+                       mfd->dma_fnc = mdp4_mddi_overlay;
+#else
+                       mfd->dma_fnc = mdp_dma2_update;
+#endif
+                       mfd->dma = &dma2_data;
+                       mfd->lut_update = mdp_lut_update_nonlcdc;
+                       mfd->do_histogram = mdp_do_histogram;
+               } else {
+                       mfd->dma_fnc = mdp_dma_s_update;
+                       mfd->dma = &dma_s_data;
+               }
+#endif
+               if (mdp_pdata)
+                       mfd->vsync_gpio = mdp_pdata->gpio;
+               else
+                       mfd->vsync_gpio = -1;
+
+#ifdef CONFIG_FB_MSM_MDP40
+               if (mfd->panel.type == EBI2_PANEL)
+                       intf = EBI2_INTF;
+               else
+                       intf = MDDI_INTF;
+
+               if (mfd->panel_info.pdest == DISPLAY_1)
+                       if_no = PRIMARY_INTF_SEL;
+               else
+                       if_no = SECONDARY_INTF_SEL;
+
+               mdp4_display_intf_sel(if_no, intf);
+#endif
+               mdp_config_vsync(mfd);
+               break;
+
+       case HDMI_PANEL:
+       case LCDC_PANEL:
+               pdata->on = mdp_lcdc_on;
+               pdata->off = mdp_lcdc_off;
+               mfd->hw_refresh = TRUE;
+               mfd->cursor_update = mdp_hw_cursor_update;
+#ifndef CONFIG_FB_MSM_MDP22
+               mfd->lut_update = mdp_lut_update_lcdc;
+               mfd->do_histogram = mdp_do_histogram;
+#endif
+#ifdef CONFIG_FB_MSM_OVERLAY
+               mfd->dma_fnc = mdp4_lcdc_overlay;
+#else
+               mfd->dma_fnc = mdp_lcdc_update;
+#endif
+
+#ifdef CONFIG_FB_MSM_MDP40
+               if (mfd->panel.type == HDMI_PANEL) {
+                       mfd->dma = &dma_e_data;
+                       mdp4_display_intf_sel(EXTERNAL_INTF_SEL, LCDC_RGB_INTF);
+               } else {
+                       mfd->dma = &dma2_data;
+                       mdp4_display_intf_sel(PRIMARY_INTF_SEL, LCDC_RGB_INTF);
+               }
+#else
+               mfd->dma = &dma2_data;
+               spin_lock_irqsave(&mdp_spin_lock, flag);
+               mdp_intr_mask &= ~MDP_DMA_P_DONE;
+               outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+               spin_unlock_irqrestore(&mdp_spin_lock, flag);
+#endif
+               break;
+
+       case TV_PANEL:
+               pdata->on = mdp_dma3_on;
+               pdata->off = mdp_dma3_off;
+               mfd->hw_refresh = TRUE;
+               mfd->dma_fnc = mdp_dma3_update;
+               mfd->dma = &dma3_data;
+               break;
+
+       default:
+               printk(KERN_ERR "mdp_probe: unknown device type!\n");
+               rc = -ENODEV;
+               goto mdp_probe_err;
+       }
+
+       /* set driver data */
+       platform_set_drvdata(msm_fb_dev, mfd);
+
+       rc = platform_device_add(msm_fb_dev);
+       if (rc) {
+               goto mdp_probe_err;
+       }
+
+       pdev_list[pdev_list_cnt++] = pdev;
+       return 0;
+
+      mdp_probe_err:
+       platform_device_put(msm_fb_dev);
+       return rc;
+}
+
+static void mdp_suspend_sub(void)
+{
+       /* cancel pipe ctrl worker */
+       cancel_delayed_work(&mdp_pipe_ctrl_worker);
+
+       /* for workder can't be cancelled... */
+       flush_workqueue(mdp_pipe_ctrl_wq);
+
+       /* let's wait for PPP completion */
+       while (mdp_block_power_cnt[MDP_PPP_BLOCK] > 0) ;
+
+       /* try to power down */
+       mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int mdp_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       mdp_suspend_sub();
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mdp_early_suspend(struct early_suspend *h)
+{
+       mdp_suspend_sub();
+}
+#endif
+
+static int mdp_remove(struct platform_device *pdev)
+{
+       iounmap(msm_mdp_base);
+       return 0;
+}
+
+static int mdp_register_driver(void)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
+       early_suspend.suspend = mdp_early_suspend;
+       register_early_suspend(&early_suspend);
+#endif
+
+       return platform_driver_register(&mdp_driver);
+}
+
+static int __init mdp_driver_init(void)
+{
+       int ret;
+
+       mdp_drv_init();
+
+       ret = mdp_register_driver();
+       if (ret) {
+               printk(KERN_ERR "mdp_register_driver() failed!\n");
+               return ret;
+       }
+
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_FB_MSM_MDP40)
+       mdp4_debugfs_init();
+#endif
+
+       return 0;
+
+}
+
+module_init(mdp_driver_init);
diff --git a/drivers/staging/msm/mdp.h b/drivers/staging/msm/mdp.h
new file mode 100644 (file)
index 0000000..0a5d6ac
--- /dev/null
@@ -0,0 +1,695 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDP_H
+#define MDP_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/hrtimer.h>
+#include "msm_mdp.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include "msm_fb_panel.h"
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+#include "mdp_ppp_dq.h"
+#endif
+
+#ifdef BIT
+#undef BIT
+#endif
+
+#define BIT(x)  (1<<(x))
+
+#define MDPOP_NOP               0
+#define MDPOP_LR                BIT(0) /* left to right flip */
+#define MDPOP_UD                BIT(1) /* up and down flip */
+#define MDPOP_ROT90             BIT(2) /* rotate image to 90 degree */
+#define MDPOP_ROT180            (MDPOP_UD|MDPOP_LR)
+#define MDPOP_ROT270            (MDPOP_ROT90|MDPOP_UD|MDPOP_LR)
+#define MDPOP_ASCALE            BIT(7)
+#define MDPOP_ALPHAB            BIT(8) /* enable alpha blending */
+#define MDPOP_TRANSP            BIT(9) /* enable transparency */
+#define MDPOP_DITHER            BIT(10)        /* enable dither */
+#define MDPOP_SHARPENING       BIT(11) /* enable sharpening */
+#define MDPOP_BLUR             BIT(12) /* enable blur */
+#define MDPOP_FG_PM_ALPHA       BIT(13)
+
+struct mdp_table_entry {
+       uint32_t reg;
+       uint32_t val;
+};
+
+extern struct mdp_ccs mdp_ccs_yuv2rgb ;
+extern struct mdp_ccs mdp_ccs_rgb2yuv ;
+
+/*
+ * MDP Image Structure
+ */
+typedef struct mdpImg_ {
+       uint32 imgType;         /* Image type */
+       uint32 *bmy_addr;       /* bitmap or y addr */
+       uint32 *cbcr_addr;      /* cbcr addr */
+       uint32 width;           /* image width */
+       uint32 mdpOp;           /* image opertion (rotation,flip up/down, alpha/tp) */
+       uint32 tpVal;           /* transparency color */
+       uint32 alpha;           /* alpha percentage 0%(0x0) ~ 100%(0x100) */
+       int    sp_value;        /* sharpening strength */
+} MDPIMG;
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+#define MDP_OUTP(addr, data)   mdp_ppp_outdw((uint32_t)(addr), \
+                                        (uint32_t)(data))
+#else
+#define MDP_OUTP(addr, data) outpdw((addr), (data))
+#endif
+
+#define MDP_KTIME2USEC(kt) (kt.tv.sec*1000000 + kt.tv.nsec/1000)
+
+#define MDP_BASE msm_mdp_base
+
+typedef enum {
+       MDP_BC_SCALE_POINT2_POINT4,
+       MDP_BC_SCALE_POINT4_POINT6,
+       MDP_BC_SCALE_POINT6_POINT8,
+       MDP_BC_SCALE_POINT8_1,
+       MDP_BC_SCALE_UP,
+       MDP_PR_SCALE_POINT2_POINT4,
+       MDP_PR_SCALE_POINT4_POINT6,
+       MDP_PR_SCALE_POINT6_POINT8,
+       MDP_PR_SCALE_POINT8_1,
+       MDP_PR_SCALE_UP,
+       MDP_SCALE_BLUR,
+       MDP_INIT_SCALE
+} MDP_SCALE_MODE;
+
+typedef enum {
+       MDP_BLOCK_POWER_OFF,
+       MDP_BLOCK_POWER_ON
+} MDP_BLOCK_POWER_STATE;
+
+typedef enum {
+       MDP_MASTER_BLOCK,
+       MDP_CMD_BLOCK,
+       MDP_PPP_BLOCK,
+       MDP_DMA2_BLOCK,
+       MDP_DMA3_BLOCK,
+       MDP_DMA_S_BLOCK,
+       MDP_DMA_E_BLOCK,
+       MDP_OVERLAY0_BLOCK,
+       MDP_OVERLAY1_BLOCK,
+       MDP_MAX_BLOCK
+} MDP_BLOCK_TYPE;
+
+/* Let's keep Q Factor power of 2 for optimization */
+#define MDP_SCALE_Q_FACTOR 512
+
+#ifdef CONFIG_FB_MSM_MDP31
+#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
+#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
+#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
+#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
+#else
+#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
+#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
+#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
+#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
+#endif
+
+/* SHIM Q Factor */
+#define PHI_Q_FACTOR          29
+#define PQF_PLUS_5            (PHI_Q_FACTOR + 5)       /* due to 32 phases */
+#define PQF_PLUS_4            (PHI_Q_FACTOR + 4)
+#define PQF_PLUS_2            (PHI_Q_FACTOR + 2)       /* to get 4.0 */
+#define PQF_MINUS_2           (PHI_Q_FACTOR - 2)       /* to get 0.25 */
+#define PQF_PLUS_5_PLUS_2     (PQF_PLUS_5 + 2)
+#define PQF_PLUS_5_MINUS_2    (PQF_PLUS_5 - 2)
+
+#define MDP_CONVTP(tpVal) (((tpVal&0xF800)<<8)|((tpVal&0x7E0)<<5)|((tpVal&0x1F)<<3))
+
+#define MDPOP_ROTATION (MDPOP_ROT90|MDPOP_LR|MDPOP_UD)
+#define MDP_CHKBIT(val, bit) ((bit) == ((val) & (bit)))
+
+/* overlay interface API defines */
+typedef enum {
+       MORE_IBUF,
+       FINAL_IBUF,
+       COMPLETE_IBUF
+} MDP_IBUF_STATE;
+
+struct mdp_dirty_region {
+       __u32 xoffset;          /* source origin in the x-axis */
+       __u32 yoffset;          /* source origin in the y-axis */
+       __u32 width;            /* number of pixels in the x-axis */
+       __u32 height;           /* number of pixels in the y-axis */
+};
+
+/*
+ * MDP extended data types
+ */
+typedef struct mdp_roi_s {
+       uint32 x;
+       uint32 y;
+       uint32 width;
+       uint32 height;
+       int32 lcd_x;
+       int32 lcd_y;
+       uint32 dst_width;
+       uint32 dst_height;
+} MDP_ROI;
+
+typedef struct mdp_ibuf_s {
+       uint8 *buf;
+       uint32 bpp;
+       uint32 ibuf_type;
+       uint32 ibuf_width;
+       uint32 ibuf_height;
+
+       MDP_ROI roi;
+       MDPIMG mdpImg;
+
+       int32 dma_x;
+       int32 dma_y;
+       uint32 dma_w;
+       uint32 dma_h;
+
+       uint32 vsync_enable;
+       uint32 visible_swapped;
+} MDPIBUF;
+
+struct mdp_dma_data {
+       boolean busy;
+       boolean waiting;
+       struct mutex ov_mutex;
+       struct semaphore mutex;
+       struct completion comp;
+};
+
+#define MDP_CMD_DEBUG_ACCESS_BASE   (MDP_BASE+0x10000)
+
+#define MDP_DMA2_TERM 0x1
+#define MDP_DMA3_TERM 0x2
+#define MDP_PPP_TERM 0x4
+#define MDP_DMA_S_TERM 0x8
+#ifdef CONFIG_FB_MSM_MDP40
+#define MDP_DMA_E_TERM 0x10
+#define MDP_OVERLAY0_TERM 0x20
+#define MDP_OVERLAY1_TERM 0x40
+#endif
+
+#define ACTIVE_START_X_EN BIT(31)
+#define ACTIVE_START_Y_EN BIT(31)
+#define ACTIVE_HIGH 0
+#define ACTIVE_LOW 1
+#define MDP_DMA_S_DONE  BIT(2)
+#define LCDC_FRAME_START    BIT(15)
+#define LCDC_UNDERFLOW      BIT(16)
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_DMA_P_DONE         BIT(2)
+#else
+#define MDP_DMA_P_DONE         BIT(14)
+#endif
+
+#define MDP_PPP_DONE                           BIT(0)
+#define TV_OUT_DMA3_DONE    BIT(6)
+#define TV_ENC_UNDERRUN     BIT(7)
+#define TV_OUT_DMA3_START   BIT(13)
+#define MDP_HIST_DONE       BIT(20)
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
+                       MDP_DMA_P_DONE| \
+                       TV_ENC_UNDERRUN)
+#else
+#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
+                       MDP_DMA_P_DONE| \
+                       MDP_DMA_S_DONE| \
+                       LCDC_UNDERFLOW| \
+                       MDP_HIST_DONE| \
+                       TV_ENC_UNDERRUN)
+#endif
+
+#define MDP_TOP_LUMA       16
+#define MDP_TOP_CHROMA     0
+#define MDP_BOTTOM_LUMA    19
+#define MDP_BOTTOM_CHROMA  3
+#define MDP_LEFT_LUMA      22
+#define MDP_LEFT_CHROMA    6
+#define MDP_RIGHT_LUMA     25
+#define MDP_RIGHT_CHROMA   9
+
+#define CLR_G 0x0
+#define CLR_B 0x1
+#define CLR_R 0x2
+#define CLR_ALPHA 0x3
+
+#define CLR_Y  CLR_G
+#define CLR_CB CLR_B
+#define CLR_CR CLR_R
+
+/* from lsb to msb */
+#define MDP_GET_PACK_PATTERN(a,x,y,z,bit) (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
+
+/*
+ * 0x0000 0x0004 0x0008 MDP sync config
+ */
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_SYNCFG_HGT_LOC 22
+#define MDP_SYNCFG_VSYNC_EXT_EN BIT(21)
+#define MDP_SYNCFG_VSYNC_INT_EN BIT(20)
+#else
+#define MDP_SYNCFG_HGT_LOC 21
+#define MDP_SYNCFG_VSYNC_EXT_EN BIT(20)
+#define MDP_SYNCFG_VSYNC_INT_EN BIT(19)
+#define MDP_HW_VSYNC
+#endif
+
+/*
+ * 0x0018 MDP VSYNC THREASH
+ */
+#define MDP_PRIM_BELOW_LOC 0
+#define MDP_PRIM_ABOVE_LOC 8
+
+/*
+ * MDP_PRIMARY_VSYNC_OUT_CTRL
+ * 0x0080,84,88 internal vsync pulse config
+ */
+#define VSYNC_PULSE_EN BIT(31)
+#define VSYNC_PULSE_INV BIT(30)
+
+/*
+ * 0x008c MDP VSYNC CONTROL
+ */
+#define DISP0_VSYNC_MAP_VSYNC0 0
+#define DISP0_VSYNC_MAP_VSYNC1 BIT(0)
+#define DISP0_VSYNC_MAP_VSYNC2 BIT(0)|BIT(1)
+
+#define DISP1_VSYNC_MAP_VSYNC0 0
+#define DISP1_VSYNC_MAP_VSYNC1 BIT(2)
+#define DISP1_VSYNC_MAP_VSYNC2 BIT(2)|BIT(3)
+
+#define PRIMARY_LCD_SYNC_EN BIT(4)
+#define PRIMARY_LCD_SYNC_DISABLE 0
+
+#define SECONDARY_LCD_SYNC_EN BIT(5)
+#define SECONDARY_LCD_SYNC_DISABLE 0
+
+#define EXTERNAL_LCD_SYNC_EN BIT(6)
+#define EXTERNAL_LCD_SYNC_DISABLE 0
+
+/*
+ * 0x101f0 MDP VSYNC Threshold
+ */
+#define VSYNC_THRESHOLD_ABOVE_LOC 0
+#define VSYNC_THRESHOLD_BELOW_LOC 16
+#define VSYNC_ANTI_TEAR_EN BIT(31)
+
+/*
+ * 0x10004 command config
+ */
+#define MDP_CMD_DBGBUS_EN BIT(0)
+
+/*
+ * 0x10124 or 0x101d4PPP source config
+ */
+#define PPP_SRC_C0G_8BITS (BIT(1)|BIT(0))
+#define PPP_SRC_C1B_8BITS (BIT(3)|BIT(2))
+#define PPP_SRC_C2R_8BITS (BIT(5)|BIT(4))
+#define PPP_SRC_C3A_8BITS (BIT(7)|BIT(6))
+
+#define PPP_SRC_C0G_6BITS BIT(1)
+#define PPP_SRC_C1B_6BITS BIT(3)
+#define PPP_SRC_C2R_6BITS BIT(5)
+
+#define PPP_SRC_C0G_5BITS BIT(0)
+#define PPP_SRC_C1B_5BITS BIT(2)
+#define PPP_SRC_C2R_5BITS BIT(4)
+
+#define PPP_SRC_C3_ALPHA_EN BIT(8)
+
+#define PPP_SRC_BPP_INTERLVD_1BYTES 0
+#define PPP_SRC_BPP_INTERLVD_2BYTES BIT(9)
+#define PPP_SRC_BPP_INTERLVD_3BYTES BIT(10)
+#define PPP_SRC_BPP_INTERLVD_4BYTES (BIT(10)|BIT(9))
+
+#define PPP_SRC_BPP_ROI_ODD_X BIT(11)
+#define PPP_SRC_BPP_ROI_ODD_Y BIT(12)
+#define PPP_SRC_INTERLVD_2COMPONENTS BIT(13)
+#define PPP_SRC_INTERLVD_3COMPONENTS BIT(14)
+#define PPP_SRC_INTERLVD_4COMPONENTS (BIT(14)|BIT(13))
+
+/*
+ * RGB666 unpack format
+ * TIGHT means R6+G6+B6 together
+ * LOOSE means R6+2 +G6+2+ B6+2 (with MSB)
+ * or 2+R6 +2+G6 +2+B6 (with LSB)
+ */
+#define PPP_SRC_UNPACK_TIGHT BIT(17)
+#define PPP_SRC_UNPACK_LOOSE 0
+#define PPP_SRC_UNPACK_ALIGN_LSB 0
+#define PPP_SRC_UNPACK_ALIGN_MSB BIT(18)
+
+#define PPP_SRC_FETCH_PLANES_INTERLVD 0
+#define PPP_SRC_FETCH_PLANES_PSEUDOPLNR BIT(20)
+
+#define PPP_SRC_WMV9_MODE BIT(21)      /* window media version 9 */
+
+/*
+ * 0x10138 PPP operation config
+ */
+#define PPP_OP_SCALE_X_ON BIT(0)
+#define PPP_OP_SCALE_Y_ON BIT(1)
+
+#define PPP_OP_CONVERT_RGB2YCBCR 0
+#define PPP_OP_CONVERT_YCBCR2RGB BIT(2)
+#define PPP_OP_CONVERT_ON BIT(3)
+
+#define PPP_OP_CONVERT_MATRIX_PRIMARY 0
+#define PPP_OP_CONVERT_MATRIX_SECONDARY BIT(4)
+
+#define PPP_OP_LUT_C0_ON BIT(5)
+#define PPP_OP_LUT_C1_ON BIT(6)
+#define PPP_OP_LUT_C2_ON BIT(7)
+
+/* rotate or blend enable */
+#define PPP_OP_ROT_ON BIT(8)
+
+#define PPP_OP_ROT_90 BIT(9)
+#define PPP_OP_FLIP_LR BIT(10)
+#define PPP_OP_FLIP_UD BIT(11)
+
+#define PPP_OP_BLEND_ON BIT(12)
+
+#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0
+#define PPP_OP_BLEND_DSTPIXEL_ALPHA BIT(13)
+#define PPP_OP_BLEND_CONSTANT_ALPHA BIT(14)
+#define PPP_OP_BLEND_SRCPIXEL_TRANSP (BIT(13)|BIT(14))
+
+#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0
+#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE BIT(15)
+
+#define PPP_OP_DITHER_EN BIT(16)
+
+#define PPP_OP_COLOR_SPACE_RGB 0
+#define PPP_OP_COLOR_SPACE_YCBCR BIT(17)
+
+#define PPP_OP_SRC_CHROMA_RGB 0
+#define PPP_OP_SRC_CHROMA_H2V1 BIT(18)
+#define PPP_OP_SRC_CHROMA_H1V2 BIT(19)
+#define PPP_OP_SRC_CHROMA_420 (BIT(18)|BIT(19))
+#define PPP_OP_SRC_CHROMA_COSITE 0
+#define PPP_OP_SRC_CHROMA_OFFSITE BIT(20)
+
+#define PPP_OP_DST_CHROMA_RGB 0
+#define PPP_OP_DST_CHROMA_H2V1 BIT(21)
+#define PPP_OP_DST_CHROMA_H1V2 BIT(22)
+#define PPP_OP_DST_CHROMA_420 (BIT(21)|BIT(22))
+#define PPP_OP_DST_CHROMA_COSITE 0
+#define PPP_OP_DST_CHROMA_OFFSITE BIT(23)
+
+#define PPP_BLEND_CALPHA_TRNASP BIT(24)
+
+#define PPP_OP_BG_CHROMA_RGB 0
+#define PPP_OP_BG_CHROMA_H2V1 BIT(25)
+#define PPP_OP_BG_CHROMA_H1V2 BIT(26)
+#define PPP_OP_BG_CHROMA_420 BIT(25)|BIT(26)
+#define PPP_OP_BG_CHROMA_SITE_COSITE 0
+#define PPP_OP_BG_CHROMA_SITE_OFFSITE BIT(27)
+#define PPP_OP_DEINT_EN BIT(29)
+
+#define PPP_BLEND_BG_USE_ALPHA_SEL      (1 << 0)
+#define PPP_BLEND_BG_ALPHA_REVERSE      (1 << 3)
+#define PPP_BLEND_BG_SRCPIXEL_ALPHA     (0 << 1)
+#define PPP_BLEND_BG_DSTPIXEL_ALPHA     (1 << 1)
+#define PPP_BLEND_BG_CONSTANT_ALPHA     (2 << 1)
+#define PPP_BLEND_BG_CONST_ALPHA_VAL(x) ((x) << 24)
+
+#define PPP_OP_DST_RGB 0
+#define PPP_OP_DST_YCBCR BIT(30)
+/*
+ * 0x10150 PPP destination config
+ */
+#define PPP_DST_C0G_8BIT (BIT(0)|BIT(1))
+#define PPP_DST_C1B_8BIT (BIT(3)|BIT(2))
+#define PPP_DST_C2R_8BIT (BIT(5)|BIT(4))
+#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
+
+#define PPP_DST_C0G_6BIT BIT(1)
+#define PPP_DST_C1B_6BIT BIT(3)
+#define PPP_DST_C2R_6BIT BIT(5)
+
+#define PPP_DST_C0G_5BIT BIT(0)
+#define PPP_DST_C1B_5BIT BIT(2)
+#define PPP_DST_C2R_5BIT BIT(4)
+
+#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
+#define PPP_DST_C3ALPHA_EN BIT(8)
+
+#define PPP_DST_PACKET_CNT_INTERLVD_2ELEM BIT(9)
+#define PPP_DST_PACKET_CNT_INTERLVD_3ELEM BIT(10)
+#define PPP_DST_PACKET_CNT_INTERLVD_4ELEM (BIT(10)|BIT(9))
+#define PPP_DST_PACKET_CNT_INTERLVD_6ELEM (BIT(11)|BIT(9))
+
+#define PPP_DST_PACK_LOOSE 0
+#define PPP_DST_PACK_TIGHT BIT(13)
+#define PPP_DST_PACK_ALIGN_LSB 0
+#define PPP_DST_PACK_ALIGN_MSB BIT(14)
+
+#define PPP_DST_OUT_SEL_AXI 0
+#define PPP_DST_OUT_SEL_MDDI BIT(15)
+
+#define PPP_DST_BPP_2BYTES BIT(16)
+#define PPP_DST_BPP_3BYTES BIT(17)
+#define PPP_DST_BPP_4BYTES (BIT(17)|BIT(16))
+
+#define PPP_DST_PLANE_INTERLVD 0
+#define PPP_DST_PLANE_PLANAR BIT(18)
+#define PPP_DST_PLANE_PSEUDOPLN BIT(19)
+
+#define PPP_DST_TO_TV BIT(20)
+
+#define PPP_DST_MDDI_PRIMARY 0
+#define PPP_DST_MDDI_SECONDARY BIT(21)
+#define PPP_DST_MDDI_EXTERNAL BIT(22)
+
+/*
+ * 0x10180 DMA config
+ */
+#define DMA_DSTC0G_8BITS (BIT(1)|BIT(0))
+#define DMA_DSTC1B_8BITS (BIT(3)|BIT(2))
+#define DMA_DSTC2R_8BITS (BIT(5)|BIT(4))
+
+#define DMA_DSTC0G_6BITS BIT(1)
+#define DMA_DSTC1B_6BITS BIT(3)
+#define DMA_DSTC2R_6BITS BIT(5)
+
+#define DMA_DSTC0G_5BITS BIT(0)
+#define DMA_DSTC1B_5BITS BIT(2)
+#define DMA_DSTC2R_5BITS BIT(4)
+
+#define DMA_PACK_TIGHT                      BIT(6)
+#define DMA_PACK_LOOSE                      0
+#define DMA_PACK_ALIGN_LSB                  0
+/*
+ * use DMA_PACK_ALIGN_MSB if the upper 6 bits from 8 bits output
+ * from LCDC block maps into 6 pins out to the panel
+ */
+#define DMA_PACK_ALIGN_MSB                  BIT(7)
+#define DMA_PACK_PATTERN_RGB \
+       (MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
+#define DMA_PACK_PATTERN_BGR \
+       (MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 2)<<8)
+#define DMA_OUT_SEL_AHB                     0
+#define DMA_OUT_SEL_LCDC                    BIT(20)
+#define DMA_IBUF_FORMAT_RGB888              0
+#define DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888  BIT(26)
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define DMA_OUT_SEL_MDDI BIT(14)
+#define DMA_AHBM_LCD_SEL_PRIMARY 0
+#define DMA_AHBM_LCD_SEL_SECONDARY BIT(15)
+#define DMA_IBUF_C3ALPHA_EN BIT(16)
+#define DMA_DITHER_EN BIT(17)
+#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
+#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY BIT(18)
+#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL BIT(19)
+#define DMA_IBUF_FORMAT_RGB565 BIT(20)
+#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
+#define DMA_IBUF_NONCONTIGUOUS BIT(21)
+#else
+#define DMA_OUT_SEL_MDDI                    BIT(19)
+#define DMA_AHBM_LCD_SEL_PRIMARY            0
+#define DMA_AHBM_LCD_SEL_SECONDARY          0
+#define DMA_IBUF_C3ALPHA_EN                 0
+#define DMA_DITHER_EN                       BIT(24)
+#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY     0
+#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY   0
+#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL    0
+#define DMA_IBUF_FORMAT_RGB565              BIT(25)
+#define DMA_IBUF_NONCONTIGUOUS 0
+#endif
+
+/*
+ * MDDI Register
+ */
+#define MDDI_VDO_PACKET_DESC  0x5666
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define MDP_INTR_ENABLE                (msm_mdp_base + 0x0050)
+#define MDP_INTR_STATUS                (msm_mdp_base + 0x0054)
+#define MDP_INTR_CLEAR         (msm_mdp_base + 0x0058)
+#define MDP_EBI2_LCD0          (msm_mdp_base + 0x0060)
+#define MDP_EBI2_LCD1          (msm_mdp_base + 0x0064)
+#define MDP_EBI2_PORTMAP_MODE  (msm_mdp_base + 0x0070)
+
+#define MDP_DMA_P_HIST_INTR_STATUS     (msm_mdp_base + 0x95014)
+#define MDP_DMA_P_HIST_INTR_CLEAR      (msm_mdp_base + 0x95018)
+#define MDP_DMA_P_HIST_INTR_ENABLE     (msm_mdp_base + 0x9501C)
+#else
+#define MDP_INTR_ENABLE                (msm_mdp_base + 0x0020)
+#define MDP_INTR_STATUS                (msm_mdp_base + 0x0024)
+#define MDP_INTR_CLEAR         (msm_mdp_base + 0x0028)
+#define MDP_EBI2_LCD0          (msm_mdp_base + 0x003c)
+#define MDP_EBI2_LCD1          (msm_mdp_base + 0x0040)
+#define MDP_EBI2_PORTMAP_MODE  (msm_mdp_base + 0x005c)
+#endif
+
+#define MDP_FULL_BYPASS_WORD43  (msm_mdp_base + 0x101ac)
+
+#define MDP_CSC_PFMVn(n)       (msm_mdp_base + 0x40400 + 4 * (n))
+#define MDP_CSC_PRMVn(n)       (msm_mdp_base + 0x40440 + 4 * (n))
+#define MDP_CSC_PRE_BV1n(n)    (msm_mdp_base + 0x40500 + 4 * (n))
+#define MDP_CSC_PRE_BV2n(n)    (msm_mdp_base + 0x40540 + 4 * (n))
+#define MDP_CSC_POST_BV1n(n)   (msm_mdp_base + 0x40580 + 4 * (n))
+#define MDP_CSC_POST_BV2n(n)   (msm_mdp_base + 0x405c0 + 4 * (n))
+
+#ifdef CONFIG_FB_MSM_MDP31
+#define MDP_CSC_PRE_LV1n(n)    (msm_mdp_base + 0x40600 + 4 * (n))
+#define MDP_CSC_PRE_LV2n(n)    (msm_mdp_base + 0x40640 + 4 * (n))
+#define MDP_CSC_POST_LV1n(n)   (msm_mdp_base + 0x40680 + 4 * (n))
+#define MDP_CSC_POST_LV2n(n)   (msm_mdp_base + 0x406c0 + 4 * (n))
+#define MDP_PPP_SCALE_COEFF_LSBn(n)    (msm_mdp_base + 0x50400 + 8 * (n))
+#define MDP_PPP_SCALE_COEFF_MSBn(n)    (msm_mdp_base + 0x50404 + 8 * (n))
+
+#define SCALE_D0_SET  0
+#define SCALE_D1_SET  BIT(0)
+#define SCALE_D2_SET  BIT(1)
+#define SCALE_U1_SET  (BIT(0)|BIT(1))
+
+#else
+#define MDP_CSC_PRE_LV1n(n)    (msm_mdp_base + 0x40580 + 4 * (n))
+#endif
+
+#define MDP_CURSOR_WIDTH 64
+#define MDP_CURSOR_HEIGHT 64
+#define MDP_CURSOR_SIZE (MDP_CURSOR_WIDTH*MDP_CURSOR_WIDTH*4)
+
+#define MDP_DMA_P_LUT_C0_EN   BIT(0)
+#define MDP_DMA_P_LUT_C1_EN   BIT(1)
+#define MDP_DMA_P_LUT_C2_EN   BIT(2)
+#define MDP_DMA_P_LUT_POST    BIT(4)
+
+void mdp_hw_init(void);
+int mdp_ppp_pipe_wait(void);
+void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd);
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+                  boolean isr);
+void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
+                         boolean sync);
+void mdp_dma_pan_update(struct fb_info *info);
+void mdp_refresh_screen(unsigned long data);
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+               struct file **pp_src, struct file **pp_dest);
+void mdp_lcd_update_workqueue_handler(struct work_struct *work);
+void mdp_vsync_resync_workqueue_handler(struct work_struct *work);
+void mdp_dma2_update(struct msm_fb_data_type *mfd);
+void mdp_config_vsync(struct msm_fb_data_type *);
+uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd);
+enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht);
+void mdp_set_scale(MDPIBUF *iBuf,
+                  uint32 dst_roi_width,
+                  uint32 dst_roi_height,
+                  boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr);
+void mdp_init_scale_table(void);
+void mdp_adjust_start_addr(uint8 **src0,
+                          uint8 **src1,
+                          int v_slice,
+                          int h_slice,
+                          int x,
+                          int y,
+                          uint32 width,
+                          uint32 height, int bpp, MDPIBUF *iBuf, int layer);
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+                       uint32 *alpha,
+                       uint32 *tpVal,
+                       uint32 perPixelAlpha, uint32 *pppop_reg_ptr);
+
+int mdp_dma3_on(struct platform_device *pdev);
+int mdp_dma3_off(struct platform_device *pdev);
+void mdp_dma3_update(struct msm_fb_data_type *mfd);
+
+int mdp_lcdc_on(struct platform_device *pdev);
+int mdp_lcdc_off(struct platform_device *pdev);
+void mdp_lcdc_update(struct msm_fb_data_type *mfd);
+int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor);
+void mdp_enable_irq(uint32 term);
+void mdp_disable_irq(uint32 term);
+void mdp_disable_irq_nolock(uint32 term);
+uint32_t mdp_get_bytes_per_pixel(uint32_t format);
+
+#ifdef MDP_HW_VSYNC
+void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd);
+void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd);
+#endif
+
+void mdp_dma_s_update(struct msm_fb_data_type *mfd);
+
+/* Added to support flipping */
+void mdp_set_offset_info(struct fb_info *info, uint32 address, uint32 interval);
+
+int get_gem_img(struct mdp_img *img, unsigned long *start,
+               unsigned long *len);
+int get_img(struct mdp_img *img, struct fb_info *info,
+               unsigned long *start, unsigned long *len,
+               struct file **pp_file);
+
+
+/*int get_img(struct msmfb_data *img, struct fb_info *info,
+       unsigned long *start, unsigned long *len, struct file **pp_file);*/
+#endif /* MDP_H */
diff --git a/drivers/staging/msm/mdp4.h b/drivers/staging/msm/mdp4.h
new file mode 100644 (file)
index 0000000..26ec8f1
--- /dev/null
@@ -0,0 +1,352 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDP4_H
+#define MDP4_H
+
+extern struct mdp_dma_data dma2_data;
+extern struct mdp_dma_data dma_s_data;
+extern struct mdp_dma_data dma_e_data;
+extern struct mdp_histogram mdp_hist;
+extern struct completion mdp_hist_comp;
+extern boolean mdp_is_in_isr;
+extern uint32 mdp_intr_mask;
+extern spinlock_t mdp_spin_lock;
+
+
+#define MDP4_NONBLOCKING       /* enable non blocking ioctl */
+
+#define MDP4_OVERLAYPROC0_BASE 0x10000
+#define MDP4_OVERLAYPROC1_BASE 0x18000
+
+#define MDP4_VIDEO_BASE 0x20000
+#define MDP4_VIDEO_OFF 0x10000
+
+#define MDP4_RGB_BASE 0x40000
+#define MDP4_RGB_OFF 0x10000
+
+enum {         /* display */
+       PRIMARY_INTF_SEL,
+       SECONDARY_INTF_SEL,
+       EXTERNAL_INTF_SEL
+};
+
+enum {
+       LCDC_RGB_INTF,
+       DTV_INTF = LCDC_RGB_INTF,
+       MDDI_LCDC_INTF,
+       MDDI_INTF,
+       EBI2_INTF
+};
+
+enum {
+       MDDI_PRIMARY_SET,
+       MDDI_SECONDARY_SET,
+       MDDI_EXTERNAL_SET
+};
+
+enum {
+       EBI2_LCD0,
+       EBI2_LCD1
+};
+
+enum {
+       OVERLAY_MODE_NONE,
+       OVERLAY_MODE_BLT
+};
+
+enum {
+       OVERLAY_REFRESH_ON_DEMAND,
+       OVERLAY_REFRESH_VSYNC,
+       OVERLAY_REFRESH_VSYNC_HALF,
+       OVERLAY_REFRESH_VSYNC_QUARTER
+};
+
+enum {
+       OVERLAY_FRAMEBUF,
+       OVERLAY_DIRECTOUT
+};
+
+/* system interrupts */
+#define INTR_OVERLAY0_DONE             BIT(0)
+#define INTR_OVERLAY1_DONE             BIT(1)
+#define INTR_DMA_S_DONE                        BIT(2)
+#define INTR_DMA_E_DONE                        BIT(3)
+#define INTR_DMA_P_DONE                        BIT(4)
+#define INTR_VG1_HISTOGRAM             BIT(5)
+#define INTR_VG2_HISTOGRAM             BIT(6)
+#define INTR_PRIMARY_VSYNC             BIT(7)
+#define INTR_PRIMARY_INTF_UDERRUN      BIT(8)
+#define INTR_EXTERNAL_VSYNC            BIT(9)
+#define INTR_EXTERNAL_INTF_UDERRUN     BIT(10)
+#define INTR_DMA_P_HISTOGRAM           BIT(17)
+
+/* histogram interrupts */
+#define INTR_HIST_DONE                 BIT(0)
+#define INTR_HIST_RESET_SEQ_DONE       BIT(1)
+
+
+#ifdef CONFIG_FB_MSM_OVERLAY
+#define MDP4_ANY_INTR_MASK     (INTR_OVERLAY0_DONE)
+#else
+#define MDP4_ANY_INTR_MASK     (INTR_DMA_P_DONE)
+#endif
+
+enum {
+       OVERLAY_PIPE_RGB1,
+       OVERLAY_PIPE_RGB2,
+};
+
+enum {
+       OVERLAY_PIPE_VG1,       /* video/graphic */
+       OVERLAY_PIPE_VG2
+};
+
+enum {
+       OVERLAY_TYPE_RGB,
+       OVERLAY_TYPE_VG         /* video/graphic */
+};
+
+enum {
+       MDP4_MIXER0,
+       MDP4_MIXER1
+};
+
+#define MDP4_MAX_MIXER 2
+
+enum {
+       OVERLAY_PLANE_INTERLEAVED,
+       OVERLAY_PLANE_PLANAR,
+       OVERLAY_PLANE_PSEUDO_PLANAR
+};
+
+enum {
+       MDP4_MIXER_STAGE_UNUNSED,       /* pipe not used */
+       MDP4_MIXER_STAGE_BASE,
+       MDP4_MIXER_STAGE0,      /* zorder 0 */
+       MDP4_MIXER_STAGE1,      /* zorder 1 */
+       MDP4_MIXER_STAGE2       /* zorder 2 */
+};
+
+#define MDP4_MAX_STAGE 4
+
+enum {
+       MDP4_FRAME_FORMAT_LINEAR,
+       MDP4_FRAME_FORMAT_ARGB_TILE,
+       MDP4_FRAME_FORMAT_VIDEO_SUPERTILE
+};
+
+enum {
+       MDP4_CHROMA_RGB,
+       MDP4_CHROMA_H2V1,
+       MDP4_CHROMA_H1V2,
+       MDP4_CHROMA_420
+};
+
+#define MDP4_BLEND_BG_TRANSP_EN                BIT(9)
+#define MDP4_BLEND_FG_TRANSP_EN                BIT(8)
+#define MDP4_BLEND_BG_MOD_ALPHA                BIT(7)
+#define MDP4_BLEND_BG_INV_ALPHA                BIT(6)
+#define MDP4_BLEND_BG_ALPHA_FG_CONST   (0 << 4)
+#define MDP4_BLEND_BG_ALPHA_BG_CONST   (1 << 4)
+#define MDP4_BLEND_BG_ALPHA_FG_PIXEL   (2 << 4)
+#define MDP4_BLEND_BG_ALPHA_BG_PIXEL   (3 << 4)
+#define MDP4_BLEND_FG_MOD_ALPHA                BIT(3)
+#define MDP4_BLEND_FG_INV_ALPHA                BIT(2)
+#define MDP4_BLEND_FG_ALPHA_FG_CONST   (0 << 0)
+#define MDP4_BLEND_FG_ALPHA_BG_CONST   (1 << 0)
+#define MDP4_BLEND_FG_ALPHA_FG_PIXEL   (2 << 0)
+#define MDP4_BLEND_FG_ALPHA_BG_PIXEL   (3 << 0)
+
+#define MDP4_FORMAT_SOLID_FILL         BIT(22)
+#define MDP4_FORMAT_UNPACK_ALIGN_MSB   BIT(18)
+#define MDP4_FORMAT_UNPACK_TIGHT       BIT(17)
+#define MDP4_FORMAT_90_ROTATED         BIT(12)
+#define MDP4_FORMAT_ALPHA_ENABLE       BIT(8)
+
+#define MDP4_OP_DEINT_ODD_REF          BIT(19)
+#define MDP4_OP_IGC_LUT_EN     BIT(16)
+#define MDP4_OP_DITHER_EN      BIT(15)
+#define MDP4_OP_FLIP_UD                BIT(14)
+#define MDP4_OP_FLIP_LR                BIT(13)
+#define MDP4_OP_CSC_EN         BIT(11)
+#define MDP4_OP_SRC_DATA_YCBCR BIT(9)
+#define MDP4_OP_SCALEY_FIR             (0 << 4)
+#define MDP4_OP_SCALEY_MN_PHASE        (1 << 4)
+#define MDP4_OP_SCALEY_PIXEL_RPT       (2 << 4)
+#define MDP4_OP_SCALEX_FIR             (0 << 2)
+#define MDP4_OP_SCALEX_MN_PHASE        (1 << 2)
+#define MDP4_OP_SCALEX_PIXEL_RPT       (2 << 2)
+#define MDP4_OP_SCALEY_EN      BIT(1)
+#define MDP4_OP_SCALEX_EN      BIT(0)
+
+#define MDP4_PIPE_PER_MIXER    2
+
+#define MDP4_MAX_PLANE         4
+
+#define MDP4_MAX_VIDEO_PIPE 2
+#define MDP4_MAX_RGB_PIPE 2
+#define MDP4_MAX_OVERLAY_PIPE  16
+
+
+struct mdp4_overlay_pipe {
+       uint32 pipe_type;               /* rgb, video/graphic */
+       uint32 pipe_num;
+       uint32 pipe_ndx;
+       uint32 mixer_num;               /* which mixer used */
+       uint32 mixer_stage;             /* which stage of mixer used */
+       uint32 src_format;
+       uint32 src_width;       /* source img width */
+       uint32 src_height;      /* source img height */
+       uint32 src_w;           /* roi */
+       uint32 src_h;           /* roi */
+       uint32 src_x;           /* roi */
+       uint32 src_y;           /* roi */
+       uint32 dst_w;           /* roi */
+       uint32 dst_h;           /* roi */
+       uint32 dst_x;           /* roi */
+       uint32 dst_y;           /* roi */
+       uint32 op_mode;
+       uint32 transp;
+       uint32 blend_op;
+       uint32 phasex_step;
+       uint32 phasey_step;
+       uint32 alpha;
+       uint32 is_fg;           /* control alpha & color key */
+       uint32 srcp0_addr;      /* interleave, luma */
+       uint32 srcp0_ystride;
+       uint32 srcp1_addr;      /* pseudoplanar, chroma plane */
+       uint32 srcp1_ystride;
+       uint32 srcp2_addr;      /* planar color 2*/
+       uint32 srcp2_ystride;
+       uint32 srcp3_addr;      /* alpha/color 3 */
+       uint32 srcp3_ystride;
+       uint32 fetch_plane;
+       uint32 frame_format;            /* video */
+       uint32 chroma_site;             /* video */
+       uint32 chroma_sample;           /* video */
+       uint32 solid_fill;
+       uint32 vc1_reduce;              /* video */
+       uint32 fatch_planes;            /* video */
+       uint32 unpack_align_msb;/* 0 to LSB, 1 to MSB */
+       uint32 unpack_tight;/* 0 for loose, 1 for tight */
+       uint32 unpack_count;/* 0 = 1 component, 1 = 2 component ... */
+       uint32 rotated_90; /* has been rotated 90 degree */
+       uint32 bpp;     /* byte per pixel */
+       uint32 alpha_enable;/*  source has alpha */
+       /*
+        * number of bits for source component,
+        * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits
+        */
+       uint32 a_bit;   /* component 3, alpha */
+       uint32 r_bit;   /* component 2, R_Cr */
+       uint32 b_bit;   /* component 1, B_Cb */
+       uint32 g_bit;   /* component 0, G_lumz */
+       /*
+        * unpack pattern
+        * A = C3, R = C2, B = C1, G = C0
+        */
+       uint32 element3; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+       uint32 element2; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+       uint32 element1; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+       uint32 element0; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+       struct completion comp;
+       struct mdp_overlay req_data;
+};
+
+void mdp4_sw_reset(unsigned long bits);
+void mdp4_display_intf_sel(int output, unsigned long intf);
+void mdp4_overlay_cfg(int layer, int blt_mode, int refresh, int direct_out);
+void mdp4_ebi2_lcd_setup(int lcd, unsigned long base, int ystride);
+void mdp4_mddi_setup(int which, unsigned long id);
+unsigned long mdp4_display_status(void);
+void mdp4_enable_clk_irq(void);
+void mdp4_disable_clk_irq(void);
+void mdp4_dma_p_update(struct msm_fb_data_type *mfd);
+void mdp4_dma_s_update(struct msm_fb_data_type *mfd);
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+                  boolean isr);
+void mdp4_pipe_kickoff(uint32 pipe, struct msm_fb_data_type *mfd);
+int mdp4_lcdc_on(struct platform_device *pdev);
+int mdp4_lcdc_off(struct platform_device *pdev);
+void mdp4_lcdc_update(struct msm_fb_data_type *mfd);
+void mdp4_intr_clear_set(ulong clear, ulong set);
+void mdp4_dma_p_cfg(void);
+void mdp4_hw_init(void);
+void mdp4_isr_read(int);
+void mdp4_clear_lcdc(void);
+void mdp4_mixer_blend_init(int mixer_num);
+void mdp4_vg_qseed_init(int vg_num);
+void mdp4_vg_csc_mv_setup(int vp_num);
+void mdp4_vg_csc_pre_bv_setup(int vp_num);
+void mdp4_vg_csc_post_bv_setup(int vp_num);
+void mdp4_vg_csc_pre_lv_setup(int vp_num);
+void mdp4_vg_csc_post_lv_setup(int vp_num);
+irqreturn_t mdp4_isr(int irq, void *ptr);
+void mdp4_overlay_format_to_pipe(uint32 format, struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
+void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
+void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all);
+void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe);
+void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe);
+void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe);
+int mdp4_mixer_stage_can_run(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe);
+void mdp4_mddi_overlay(struct msm_fb_data_type *mfd);
+int mdp4_overlay_format2type(uint32 format);
+int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
+int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
+int mdp4_overlay_unset(struct fb_info *info, int ndx);
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
+                               struct file **pp_src_file);
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void);
+void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc);
+void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_active(int mixer);
+void mdp4_overlay0_done_lcdc(void);
+void mdp4_overlay0_done_mddi(void);
+void mdp4_mddi_overlay_restore(void);
+void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
+                               struct mdp4_overlay_pipe *pipe);
+void mdp4_rgb_igc_lut_setup(int num);
+void mdp4_vg_igc_lut_setup(int num);
+void mdp4_mixer_gc_lut_setup(int mixer_num);
+
+#ifdef CONFIG_DEBUG_FS
+int mdp4_debugfs_init(void);
+#endif
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+       struct file **pp_src_file, struct file **pp_dst_file);
+
+#endif /* MDP_H */
diff --git a/drivers/staging/msm/mdp4_debugfs.c b/drivers/staging/msm/mdp4_debugfs.c
new file mode 100644 (file)
index 0000000..844d467
--- /dev/null
@@ -0,0 +1,181 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+
+#define MDP4_DEBUG_BUF 128
+
+
+static char mdp4_debug_buf[MDP4_DEBUG_BUF];
+static ulong mdp4_debug_offset;
+static ulong mdp4_base_addr;
+
+static int mdp4_offset_set(void *data, u64 val)
+{
+       mdp4_debug_offset = (int)val;
+       return 0;
+}
+
+static int mdp4_offset_get(void *data, u64 *val)
+{
+       *val = (u64)mdp4_debug_offset;
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(
+                       mdp4_offset_fops,
+                       mdp4_offset_get,
+                       mdp4_offset_set,
+                       "%llx\n");
+
+
+static int mdp4_debugfs_open(struct inode *inode, struct file *file)
+{
+       /* non-seekable */
+       file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+       return 0;
+}
+
+static int mdp4_debugfs_release(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+
+static ssize_t mdp4_debugfs_write(
+       struct file *file,
+       const char __user *buff,
+       size_t count,
+       loff_t *ppos)
+{
+       int cnt;
+       unsigned int data;
+
+       printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n",
+               __func__, (int)mdp4_debug_offset, (int)count, (int)*ppos);
+
+       if (count > sizeof(mdp4_debug_buf))
+               return -EFAULT;
+
+       if (copy_from_user(mdp4_debug_buf, buff, count))
+               return -EFAULT;
+
+
+       mdp4_debug_buf[count] = 0;      /* end of string */
+
+       cnt = sscanf(mdp4_debug_buf, "%x", &data);
+       if (cnt < 1) {
+               printk(KERN_ERR "%s: sscanf failed cnt=%d" , __func__, cnt);
+               return -EINVAL;
+       }
+
+       writel(&data, mdp4_base_addr + mdp4_debug_offset);
+
+       return 0;
+}
+
+static ssize_t mdp4_debugfs_read(
+       struct file *file,
+       char __user *buff,
+       size_t count,
+       loff_t *ppos)
+{
+       int len = 0;
+       unsigned int data;
+
+       printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n",
+               __func__, (int)mdp4_debug_offset, (int)count, (int)*ppos);
+
+       if (*ppos)
+               return 0;       /* the end */
+
+       data = readl(mdp4_base_addr + mdp4_debug_offset);
+
+       len = snprintf(mdp4_debug_buf, 4, "%x\n", data);
+
+       if (len > 0) {
+               if (len > count)
+                       len = count;
+               if (copy_to_user(buff, mdp4_debug_buf, len))
+                       return -EFAULT;
+       }
+
+       printk(KERN_INFO "%s: len=%d\n", __func__, len);
+
+       if (len < 0)
+               return 0;
+
+       *ppos += len;   /* increase offset */
+
+       return len;
+}
+
+static const struct file_operations mdp4_debugfs_fops = {
+       .open = mdp4_debugfs_open,
+       .release = mdp4_debugfs_release,
+       .read = mdp4_debugfs_read,
+       .write = mdp4_debugfs_write,
+};
+
+int mdp4_debugfs_init(void)
+{
+       struct dentry *dent = debugfs_create_dir("mdp4", NULL);
+
+       if (IS_ERR(dent)) {
+               printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+                       __FILE__, __LINE__, PTR_ERR(dent));
+               return -1;
+       }
+
+       if (debugfs_create_file("offset", 0644, dent, 0, &mdp4_offset_fops)
+                       == NULL) {
+               printk(KERN_ERR "%s(%d): debugfs_create_file: offset fail\n",
+                       __FILE__, __LINE__);
+               return -1;
+       }
+
+       if (debugfs_create_file("regs", 0644, dent, 0, &mdp4_debugfs_fops)
+                       == NULL) {
+               printk(KERN_ERR "%s(%d): debugfs_create_file: regs fail\n",
+                       __FILE__, __LINE__);
+               return -1;
+       }
+
+       mdp4_debug_offset = 0;
+       mdp4_base_addr = (ulong) msm_mdp_base;  /* defined at msm_fb_def.h */
+
+       return 0;
+}
diff --git a/drivers/staging/msm/mdp4_overlay.c b/drivers/staging/msm/mdp4_overlay.c
new file mode 100644 (file)
index 0000000..304bb82
--- /dev/null
@@ -0,0 +1,1259 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/fb.h>
+#include <msm_mdp.h>
+#include <linux/file.h>
+#include "android_pmem.h"
+#include <linux/major.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/mutex.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+
+struct mdp4_overlay_ctrl {
+       struct mdp4_overlay_pipe plist[MDP4_MAX_OVERLAY_PIPE];
+       struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MAX_STAGE];
+} mdp4_overlay_db;
+
+static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
+
+
+void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc)
+{
+       uint32  dma2_cfg_reg;
+
+       dma2_cfg_reg = DMA_DITHER_EN;
+
+       if (mfd->fb_imgType == MDP_BGR_565)
+               dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+       else
+               dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+
+       if (mfd->panel_info.bpp == 18) {
+               dma2_cfg_reg |= DMA_DSTC0G_6BITS |      /* 666 18BPP */
+                   DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+       } else if (mfd->panel_info.bpp == 16) {
+               dma2_cfg_reg |= DMA_DSTC0G_6BITS |      /* 565 16BPP */
+                   DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+       } else {
+               dma2_cfg_reg |= DMA_DSTC0G_8BITS |      /* 888 16BPP */
+                   DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+       }
+
+       if (lcdc)
+               dma2_cfg_reg |= DMA_PACK_ALIGN_MSB;
+
+       /* dma2 config register */
+       MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+
+}
+
+void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
+{
+
+       /* dma_p source */
+       MDP_OUTP(MDP_BASE + 0x90004,
+                       (pipe->src_height << 16 | pipe->src_width));
+       MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr);
+       MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride);
+
+       /* dma_p dest */
+       MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x));
+}
+
+#define MDP4_VG_PHASE_STEP_DEFAULT     0x20000000
+#define MDP4_VG_PHASE_STEP_SHIFT       29
+
+static int mdp4_leading_0(uint32 num)
+{
+       uint32 bit = 0x80000000;
+       int i;
+
+       for (i = 0; i < 32; i++) {
+               if (bit & num)
+                       return i;
+               bit >>= 1;
+       }
+
+       return i;
+}
+
+static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
+{
+       uint32 val;
+       int     n;
+
+       n = mdp4_leading_0(src);
+       if (n > f_num)
+               n = f_num;
+       val = src << n; /* maximum to reduce lose of resolution */
+       val /= dst;
+       if (n < f_num) {
+               n = f_num - n;
+               val <<= n;
+       }
+
+       return val;
+}
+
+static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
+{
+
+       pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
+       pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
+
+       if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
+               if (pipe->dst_h >= pipe->src_h * 8)     /* too much */
+                       return;
+               pipe->op_mode |= MDP4_OP_SCALEY_EN;
+
+               if (pipe->pipe_type == OVERLAY_TYPE_VG) {
+                       if (pipe->dst_h <= (pipe->src_h / 4))
+                               pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
+                       else
+                               pipe->op_mode |= MDP4_OP_SCALEY_FIR;
+               }
+
+               pipe->phasey_step = mdp4_scale_phase_step(29,
+                                       pipe->src_h, pipe->dst_h);
+       }
+
+       if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
+               if (pipe->dst_w >= pipe->src_w * 8)     /* too much */
+                       return;
+               pipe->op_mode |= MDP4_OP_SCALEX_EN;
+
+               if (pipe->pipe_type == OVERLAY_TYPE_VG) {
+                       if (pipe->dst_w <= (pipe->src_w / 4))
+                               pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
+                       else
+                               pipe->op_mode |= MDP4_OP_SCALEY_FIR;
+               }
+
+               pipe->phasex_step = mdp4_scale_phase_step(29,
+                                       pipe->src_w, pipe->dst_w);
+       }
+}
+
+void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe)
+{
+       char *rgb_base;
+       uint32 src_size, src_xy, dst_size, dst_xy;
+       uint32 format, pattern;
+
+       rgb_base = MDP_BASE + MDP4_RGB_BASE;
+       rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
+
+       src_size = ((pipe->src_h << 16) | pipe->src_w);
+       src_xy = ((pipe->src_y << 16) | pipe->src_x);
+       dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
+       dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
+
+       format = mdp4_overlay_format(pipe);
+       pattern = mdp4_overlay_unpack_pattern(pipe);
+
+       pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
+
+       mdp4_scale_setup(pipe);
+
+       outpdw(rgb_base + 0x0000, src_size);    /* MDP_RGB_SRC_SIZE */
+       outpdw(rgb_base + 0x0004, src_xy);      /* MDP_RGB_SRC_XY */
+       outpdw(rgb_base + 0x0008, dst_size);    /* MDP_RGB_DST_SIZE */
+       outpdw(rgb_base + 0x000c, dst_xy);      /* MDP_RGB_DST_XY */
+
+       outpdw(rgb_base + 0x0010, pipe->srcp0_addr);
+       outpdw(rgb_base + 0x0040, pipe->srcp0_ystride);
+
+       outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */
+       outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */
+       outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
+       outpdw(rgb_base + 0x005c, pipe->phasex_step);
+       outpdw(rgb_base + 0x0060, pipe->phasey_step);
+
+       /* 16 bytes-burst x 3 req <= 48 bytes */
+       outpdw(rgb_base + 0x1004, 0xc2);        /* MDP_RGB_FETCH_CFG */
+}
+
+void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe)
+{
+       char *vg_base;
+       uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
+       uint32 format, pattern;
+
+       vg_base = MDP_BASE + MDP4_VIDEO_BASE;
+       vg_base += (MDP4_VIDEO_OFF * pipe->pipe_num);
+
+       frame_size = ((pipe->src_height << 16) | pipe->src_width);
+       src_size = ((pipe->src_h << 16) | pipe->src_w);
+       src_xy = ((pipe->src_y << 16) | pipe->src_x);
+       dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
+       dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
+
+       format = mdp4_overlay_format(pipe);
+       pattern = mdp4_overlay_unpack_pattern(pipe);
+
+       pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR |
+                               MDP4_OP_IGC_LUT_EN);
+
+       mdp4_scale_setup(pipe);
+
+       outpdw(vg_base + 0x0000, src_size);     /* MDP_RGB_SRC_SIZE */
+       outpdw(vg_base + 0x0004, src_xy);       /* MDP_RGB_SRC_XY */
+       outpdw(vg_base + 0x0008, dst_size);     /* MDP_RGB_DST_SIZE */
+       outpdw(vg_base + 0x000c, dst_xy);       /* MDP_RGB_DST_XY */
+       outpdw(vg_base + 0x0048, frame_size);   /* TILE frame size */
+
+       /* luma component plane */
+       outpdw(vg_base + 0x0010, pipe->srcp0_addr);
+
+       /* chroma component plane */
+       outpdw(vg_base + 0x0014, pipe->srcp1_addr);
+
+       outpdw(vg_base + 0x0040,
+                       pipe->srcp1_ystride << 16 | pipe->srcp0_ystride);
+
+       outpdw(vg_base + 0x0050, format);       /* MDP_RGB_SRC_FORMAT */
+       outpdw(vg_base + 0x0054, pattern);      /* MDP_RGB_SRC_UNPACK_PATTERN */
+       outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
+       outpdw(vg_base + 0x005c, pipe->phasex_step);
+       outpdw(vg_base + 0x0060, pipe->phasey_step);
+
+       if (pipe->op_mode & MDP4_OP_DITHER_EN) {
+               outpdw(vg_base + 0x0068,
+                       pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit);
+       }
+
+       /* 16 bytes-burst x 3 req <= 48 bytes */
+       outpdw(vg_base + 0x1004, 0xc2); /* MDP_VG_FETCH_CFG */
+}
+
+int mdp4_overlay_format2type(uint32 format)
+{
+       switch (format) {
+       case MDP_RGB_565:
+       case MDP_RGB_888:
+       case MDP_BGR_565:
+       case MDP_ARGB_8888:
+       case MDP_RGBA_8888:
+       case MDP_BGRA_8888:
+               return OVERLAY_TYPE_RGB;
+       case MDP_YCRYCB_H2V1:
+       case MDP_Y_CRCB_H2V1:
+       case MDP_Y_CBCR_H2V1:
+       case MDP_Y_CRCB_H2V2:
+       case MDP_Y_CBCR_H2V2:
+       case MDP_Y_CBCR_H2V2_TILE:
+       case MDP_Y_CRCB_H2V2_TILE:
+               return OVERLAY_TYPE_VG;
+       default:
+               return -ERANGE;
+       }
+
+}
+
+#define C3_ALPHA       3       /* alpha */
+#define C2_R_Cr                2       /* R/Cr */
+#define C1_B_Cb                1       /* B/Cb */
+#define C0_G_Y         0       /* G/luma */
+
+int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe)
+{
+       switch (pipe->src_format) {
+       case MDP_RGB_565:
+               pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+               pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+               pipe->a_bit = 0;
+               pipe->r_bit = 1;        /* R, 5 bits */
+               pipe->b_bit = 1;        /* B, 5 bits */
+               pipe->g_bit = 2;        /* G, 6 bits */
+               pipe->alpha_enable = 0;
+               pipe->unpack_tight = 1;
+               pipe->unpack_align_msb = 0;
+               pipe->unpack_count = 2;
+               pipe->element2 = C2_R_Cr;       /* R */
+               pipe->element1 = C0_G_Y;        /* G */
+               pipe->element0 = C1_B_Cb;       /* B */
+               pipe->bpp = 2;  /* 2 bpp */
+               break;
+       case MDP_RGB_888:
+               pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+               pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+               pipe->a_bit = 0;
+               pipe->r_bit = 3;        /* R, 8 bits */
+               pipe->b_bit = 3;        /* B, 8 bits */
+               pipe->g_bit = 3;        /* G, 8 bits */
+               pipe->alpha_enable = 0;
+               pipe->unpack_tight = 1;
+               pipe->unpack_align_msb = 0;
+               pipe->unpack_count = 2;
+               pipe->element2 = C2_R_Cr;       /* R */
+               pipe->element1 = C0_G_Y;        /* G */
+               pipe->element0 = C1_B_Cb;       /* B */
+               pipe->bpp = 3;  /* 3 bpp */
+               break;
+       case MDP_BGR_565:
+               pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+               pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+               pipe->a_bit = 0;
+               pipe->r_bit = 1;        /* R, 5 bits */
+               pipe->b_bit = 1;        /* B, 5 bits */
+               pipe->g_bit = 2;        /* G, 6 bits */
+               pipe->alpha_enable = 0;
+               pipe->unpack_tight = 1;
+               pipe->unpack_align_msb = 0;
+               pipe->unpack_count = 2;
+               pipe->element2 = C1_B_Cb;       /* B */
+               pipe->element1 = C0_G_Y;        /* G */
+               pipe->element0 = C2_R_Cr;       /* R */
+               pipe->bpp = 2;  /* 2 bpp */
+               break;
+       case MDP_ARGB_8888:
+               pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+               pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+               pipe->a_bit = 3;        /* alpha, 4 bits */
+               pipe->r_bit = 3;        /* R, 8 bits */
+               pipe->b_bit = 3;        /* B, 8 bits */
+               pipe->g_bit = 3;        /* G, 8 bits */
+               pipe->alpha_enable = 1;
+               pipe->unpack_tight = 1;
+               pipe->unpack_align_msb = 0;
+               pipe->unpack_count = 3;
+               pipe->element3 = C3_ALPHA;      /* alpha */
+               pipe->element2 = C2_R_Cr;       /* R */
+               pipe->element1 = C0_G_Y;        /* G */
+               pipe->element0 = C1_B_Cb;       /* B */
+               pipe->bpp = 4;          /* 4 bpp */
+               break;
+       case MDP_RGBA_8888:
+               pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+               pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+               pipe->a_bit = 3;        /* alpha, 4 bits */
+               pipe->r_bit = 3;        /* R, 8 bits */
+               pipe->b_bit = 3;        /* B, 8 bits */
+               pipe->g_bit = 3;        /* G, 8 bits */
+               pipe->alpha_enable = 1;
+               pipe->unpack_tight = 1;
+               pipe->unpack_align_msb = 0;
+               pipe->unpack_count = 3;
+               pipe->element3 = C2_R_Cr;       /* R */
+               pipe->element2 = C0_G_Y;        /* G */
+               pipe->element1 = C1_B_Cb;       /* B */
+               pipe->element0 = C3_ALPHA;      /* alpha */
+               pipe->bpp = 4;          /* 4 bpp */
+               break;
+       case MDP_BGRA_8888:
+               pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+               pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+               pipe->a_bit = 3;        /* alpha, 4 bits */
+               pipe->r_bit = 3;        /* R, 8 bits */
+               pipe->b_bit = 3;        /* B, 8 bits */
+               pipe->g_bit = 3;        /* G, 8 bits */
+               pipe->alpha_enable = 1;
+               pipe->unpack_tight = 1;
+               pipe->unpack_align_msb = 0;
+               pipe->unpack_count = 3;
+               pipe->element3 = C1_B_Cb;       /* B */
+               pipe->element2 = C0_G_Y;        /* G */
+               pipe->element1 = C2_R_Cr;       /* R */
+               pipe->element0 = C3_ALPHA;      /* alpha */
+               pipe->bpp = 4;          /* 4 bpp */
+               break;
+       case MDP_YCRYCB_H2V1:
+               pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+               pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+               pipe->a_bit = 0;        /* alpha, 4 bits */
+               pipe->r_bit = 3;        /* R, 8 bits */
+               pipe->b_bit = 3;        /* B, 8 bits */
+               pipe->g_bit = 3;        /* G, 8 bits */
+               pipe->alpha_enable = 0;
+               pipe->unpack_tight = 1;
+               pipe->unpack_align_msb = 0;
+               pipe->unpack_count = 3;
+               pipe->element3 = C0_G_Y;        /* G */
+               pipe->element2 = C2_R_Cr;       /* R */
+               pipe->element1 = C0_G_Y;        /* G */
+               pipe->element0 = C1_B_Cb;       /* B */
+               pipe->bpp = 2;          /* 2 bpp */
+               pipe->chroma_sample = MDP4_CHROMA_H2V1;
+               break;
+       case MDP_Y_CRCB_H2V1:
+       case MDP_Y_CBCR_H2V1:
+       case MDP_Y_CRCB_H2V2:
+       case MDP_Y_CBCR_H2V2:
+               pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+               pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
+               pipe->a_bit = 0;
+               pipe->r_bit = 3;        /* R, 8 bits */
+               pipe->b_bit = 3;        /* B, 8 bits */
+               pipe->g_bit = 3;        /* G, 8 bits */
+               pipe->alpha_enable = 0;
+               pipe->unpack_tight = 1;
+               pipe->unpack_align_msb = 0;
+               pipe->unpack_count = 1;         /* 2 */
+               pipe->element3 = C0_G_Y;        /* not used */
+               pipe->element2 = C0_G_Y;        /* not used */
+               if (pipe->src_format == MDP_Y_CRCB_H2V1) {
+                       pipe->element1 = C2_R_Cr;       /* R */
+                       pipe->element0 = C1_B_Cb;       /* B */
+                       pipe->chroma_sample = MDP4_CHROMA_H2V1;
+               } else if (pipe->src_format == MDP_Y_CBCR_H2V1) {
+                       pipe->element1 = C1_B_Cb;       /* B */
+                       pipe->element0 = C2_R_Cr;       /* R */
+                       pipe->chroma_sample = MDP4_CHROMA_H2V1;
+               } else if (pipe->src_format == MDP_Y_CRCB_H2V2) {
+                       pipe->element1 = C2_R_Cr;       /* R */
+                       pipe->element0 = C1_B_Cb;       /* B */
+                       pipe->chroma_sample = MDP4_CHROMA_420;
+               } else if (pipe->src_format == MDP_Y_CBCR_H2V2) {
+                       pipe->element1 = C1_B_Cb;       /* B */
+                       pipe->element0 = C2_R_Cr;       /* R */
+                       pipe->chroma_sample = MDP4_CHROMA_420;
+               }
+               pipe->bpp = 2;  /* 2 bpp */
+               break;
+       case MDP_Y_CBCR_H2V2_TILE:
+       case MDP_Y_CRCB_H2V2_TILE:
+               pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE;
+               pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
+               pipe->a_bit = 0;
+               pipe->r_bit = 3;        /* R, 8 bits */
+               pipe->b_bit = 3;        /* B, 8 bits */
+               pipe->g_bit = 3;        /* G, 8 bits */
+               pipe->alpha_enable = 0;
+               pipe->unpack_tight = 1;
+               pipe->unpack_align_msb = 0;
+               pipe->unpack_count = 1;         /* 2 */
+               pipe->element3 = C0_G_Y;        /* not used */
+               pipe->element2 = C0_G_Y;        /* not used */
+               if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) {
+                       pipe->element1 = C2_R_Cr;       /* R */
+                       pipe->element0 = C1_B_Cb;       /* B */
+                       pipe->chroma_sample = MDP4_CHROMA_420;
+               } else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) {
+                       pipe->element1 = C1_B_Cb;       /* B */
+                       pipe->element0 = C2_R_Cr;       /* R */
+                       pipe->chroma_sample = MDP4_CHROMA_420;
+               }
+               pipe->bpp = 2;  /* 2 bpp */
+               break;
+       default:
+               /* not likely */
+               return -ERANGE;
+       }
+
+       return 0;
+}
+
+/*
+ * color_key_convert: output with 12 bits color key
+ */
+static uint32 color_key_convert(int start, int num, uint32 color)
+{
+
+       uint32 data;
+
+       data = (color >> start) & ((1 << num) - 1);
+
+       if (num == 5)
+               data = (data << 7) + (data << 2) + (data >> 3);
+       else if (num == 6)
+               data = (data << 6) + data;
+       else    /* 8 bits */
+               data = (data << 4) + (data >> 4);
+
+       return data;
+
+}
+
+void transp_color_key(int format, uint32 transp,
+                       uint32 *c0, uint32 *c1, uint32 *c2)
+{
+       int b_start, g_start, r_start;
+       int b_num, g_num, r_num;
+
+       switch (format) {
+       case MDP_RGB_565:
+               b_start = 0;
+               g_start = 5;
+               r_start = 11;
+               r_num = 5;
+               g_num = 6;
+               b_num = 5;
+               break;
+       case MDP_RGB_888:
+       case MDP_XRGB_8888:
+       case MDP_ARGB_8888:
+               b_start = 0;
+               g_start = 8;
+               r_start = 16;
+               r_num = 8;
+               g_num = 8;
+               b_num = 8;
+               break;
+       case MDP_BGR_565:
+               b_start = 11;
+               g_start = 5;
+               r_start = 0;
+               r_num = 5;
+               g_num = 6;
+               b_num = 5;
+               break;
+       case MDP_Y_CBCR_H2V2:
+       case MDP_Y_CBCR_H2V1:
+               b_start = 8;
+               g_start = 16;
+               r_start = 0;
+               r_num = 8;
+               g_num = 8;
+               b_num = 8;
+               break;
+       case MDP_Y_CRCB_H2V2:
+       case MDP_Y_CRCB_H2V1:
+               b_start = 0;
+               g_start = 16;
+               r_start = 8;
+               r_num = 8;
+               g_num = 8;
+               b_num = 8;
+               break;
+       default:
+               b_start = 0;
+               g_start = 8;
+               r_start = 16;
+               r_num = 8;
+               g_num = 8;
+               b_num = 8;
+               break;
+       }
+
+       *c0 = color_key_convert(g_start, g_num, transp);
+       *c1 = color_key_convert(b_start, b_num, transp);
+       *c2 = color_key_convert(r_start, r_num, transp);
+}
+
+uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
+{
+       uint32  format;
+
+       format = 0;
+
+       if (pipe->solid_fill)
+               format |= MDP4_FORMAT_SOLID_FILL;
+
+       if (pipe->unpack_align_msb)
+               format |= MDP4_FORMAT_UNPACK_ALIGN_MSB;
+
+       if (pipe->unpack_tight)
+               format |= MDP4_FORMAT_UNPACK_TIGHT;
+
+       if (pipe->alpha_enable)
+               format |= MDP4_FORMAT_ALPHA_ENABLE;
+
+       format |= (pipe->unpack_count << 13);
+       format |= ((pipe->bpp - 1) << 9);
+       format |= (pipe->a_bit << 6);
+       format |= (pipe->r_bit << 4);
+       format |= (pipe->b_bit << 2);
+       format |= pipe->g_bit;
+
+       format |= (pipe->frame_format << 29);
+
+       if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
+               /* video/graphic */
+               format |= (pipe->fetch_plane << 19);
+               format |= (pipe->chroma_site << 28);
+               format |= (pipe->chroma_sample << 26);
+       }
+
+       return format;
+}
+
+uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe)
+{
+       return (pipe->element3 << 24) | (pipe->element2 << 16) |
+                       (pipe->element1 << 8) | pipe->element0;
+}
+
+void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe)
+{
+       uint32 data;
+       char *overlay_base;
+
+       if (pipe->mixer_num == MDP4_MIXER1)
+               overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+       else
+               overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+       /* MDP_OVERLAYPROC_CFG */
+       outpdw(overlay_base + 0x0004, 0x01); /* directout */
+       data = pipe->src_height;
+       data <<= 16;
+       data |= pipe->src_width;
+       outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
+       outpdw(overlay_base + 0x000c, pipe->srcp0_addr);
+       outpdw(overlay_base + 0x0010, pipe->srcp0_ystride);
+       outpdw(overlay_base + 0x0014, 0x4);     /* GC_LUT_EN, 888 */
+}
+
+int mdp4_overlay_active(int mixer)
+{
+       uint32 data, mask, i;
+       int p1, p2;
+
+       data = inpdw(MDP_BASE + 0x10100);
+       p1 = 0;
+       p2 = 0;
+       for (i = 0; i < 8; i++) {
+               mask = data & 0x0f;
+               if (mask) {
+                       if (mask <= 4)
+                               p1++;
+                       else
+                               p2++;
+               }
+               data >>= 4;
+       }
+
+       if (mixer)
+               return p2;
+       else
+               return p1;
+}
+
+void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
+{
+       uint32 data, mask, snum, stage, mixer;
+
+       stage = pipe->mixer_stage;
+       mixer = pipe->mixer_num;
+
+       /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
+       data = inpdw(MDP_BASE + 0x10100);
+
+       if (mixer == MDP4_MIXER1)
+               stage += 8;
+
+       if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
+               snum = 0;
+               snum += (4 * pipe->pipe_num);
+       } else {
+               snum = 8;
+               snum += (4 * pipe->pipe_num);   /* RGB1 and RGB2 */
+       }
+
+       mask = 0x0f;
+       mask <<= snum;
+       stage <<= snum;
+       data &= ~mask;  /* clear old bits */
+
+       data |= stage;
+
+       outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
+
+       data = inpdw(MDP_BASE + 0x10100);
+
+       ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe; /* keep it */
+}
+
+void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
+{
+       uint32 data, mask, snum, stage, mixer;
+
+       stage = pipe->mixer_stage;
+       mixer = pipe->mixer_num;
+
+       if (pipe != ctrl->stage[mixer][stage])  /* not runing */
+               return;
+
+       /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
+       data = inpdw(MDP_BASE + 0x10100);
+
+       if (mixer == MDP4_MIXER1)
+               stage += 8;
+
+       if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
+               snum = 0;
+               snum += (4 * pipe->pipe_num);
+       } else {
+               snum = 8;
+               snum += (4 * pipe->pipe_num);   /* RGB1 and RGB2 */
+       }
+
+       mask = 0x0f;
+       mask <<= snum;
+       data &= ~mask;  /* clear old bits */
+
+       outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
+
+       data = inpdw(MDP_BASE + 0x10100);
+
+       ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */
+}
+
+void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
+{
+       unsigned char *overlay_base;
+       uint32 c0, c1, c2, blend_op;
+       int off;
+
+       if (pipe->mixer_num)    /* mixer number, /dev/fb0, /dev/fb1 */
+               overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+       else
+               overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+       /* stage 0 to stage 2 */
+       off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
+
+       blend_op = 0;
+       if (pipe->alpha_enable)         /* ARGB */
+               blend_op = MDP4_BLEND_FG_ALPHA_FG_PIXEL |
+                               MDP4_BLEND_BG_ALPHA_FG_PIXEL;
+       else
+               blend_op = (MDP4_BLEND_BG_ALPHA_BG_CONST |
+                               MDP4_BLEND_FG_ALPHA_FG_CONST);
+
+
+       if (pipe->alpha_enable == 0) {  /* not ARGB */
+               if (pipe->is_fg) {
+                       outpdw(overlay_base + off + 0x108, pipe->alpha);
+                       outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
+               } else {
+                       outpdw(overlay_base + off + 0x108, 0xff - pipe->alpha);
+                       outpdw(overlay_base + off + 0x10c, pipe->alpha);
+               }
+       }
+
+       if (pipe->transp != MDP_TRANSP_NOP) {
+               transp_color_key(pipe->src_format, pipe->transp, &c0, &c1, &c2);
+               if (pipe->is_fg) {
+                       blend_op |= MDP4_BLEND_FG_TRANSP_EN; /* Fg blocked */
+                       /* lower limit */
+                       if (c0 > 0x10)
+                               c0 -= 0x10;
+                       if (c1 > 0x10)
+                               c1 -= 0x10;
+                       if (c2 > 0x10)
+                               c2 -= 0x10;
+                       outpdw(overlay_base + off + 0x110,
+                                               (c1 << 16 | c0));/* low */
+                       outpdw(overlay_base + off + 0x114, c2);/* low */
+                       /* upper limit */
+                       if ((c0 + 0x20) < 0x0fff)
+                               c0 += 0x20;
+                       else
+                               c0 = 0x0fff;
+                       if ((c1 + 0x20) < 0x0fff)
+                               c1 += 0x20;
+                       else
+                               c1 = 0x0fff;
+                       if ((c2 + 0x20) < 0x0fff)
+                               c2 += 0x20;
+                       else
+                               c2 = 0x0fff;
+                       outpdw(overlay_base + off + 0x118,
+                                       (c1 << 16 | c0));/* high */
+                       outpdw(overlay_base + off + 0x11c, c2);/* high */
+               } else {
+                       blend_op |= MDP4_BLEND_BG_TRANSP_EN; /* bg blocked */
+                       /* lower limit */
+                       if (c0 > 0x10)
+                               c0 -= 0x10;
+                       if (c1 > 0x10)
+                               c1 -= 0x10;
+                       if (c2 > 0x10)
+                               c2 -= 0x10;
+                       outpdw(overlay_base + 0x180,
+                                               (c1 << 16 | c0));/* low */
+                       outpdw(overlay_base + 0x184, c2);/* low */
+                       /* upper limit */
+                       if ((c0 + 0x20) < 0x0fff)
+                               c0 += 0x20;
+                       else
+                               c0 = 0x0fff;
+                       if ((c1 + 0x20) < 0x0fff)
+                               c1 += 0x20;
+                       else
+                               c1 = 0x0fff;
+                       if ((c2 + 0x20) < 0x0fff)
+                               c2 += 0x20;
+                       else
+                               c2 = 0x0fff;
+                       outpdw(overlay_base + 0x188,
+                                               (c1 << 16 | c0));/* high */
+                       outpdw(overlay_base + 0x18c, c2);/* high */
+               }
+       }
+       outpdw(overlay_base + off + 0x104, blend_op);
+}
+
+void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
+{
+       uint32 bits = 0;
+
+       if (pipe->mixer_num == MDP4_MIXER1)
+               bits |= 0x02;
+       else
+               bits |= 0x01;
+
+       if (all) {
+               if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
+                       if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
+                               bits |= 0x20;
+                       else
+                               bits |= 0x10;
+               } else {
+                       if (pipe->pipe_num == OVERLAY_PIPE_VG2)
+                               bits |= 0x08;
+                       else
+                               bits |= 0x04;
+               }
+       }
+
+       outpdw(MDP_BASE + 0x18000, bits);       /* MDP_OVERLAY_REG_FLUSH */
+
+       while (inpdw(MDP_BASE + 0x18000) & bits) /* self clear when complete */
+               ;
+}
+
+struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx)
+{
+       struct mdp4_overlay_pipe *pipe;
+
+       if (ndx == 0 || ndx >= MDP4_MAX_OVERLAY_PIPE)
+               return NULL;
+
+       pipe = &ctrl->plist[ndx - 1];   /* ndx start from 1 */
+
+       if (pipe->pipe_ndx == 0)
+               return NULL;
+
+       return pipe;
+}
+
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void)
+{
+       int i;
+       struct mdp4_overlay_pipe *pipe;
+
+       pipe = &ctrl->plist[0];
+       for (i = 0; i < MDP4_MAX_OVERLAY_PIPE; i++) {
+               if (pipe->pipe_ndx == 0) {
+                       pipe->pipe_ndx = i + 1; /* start from 1 */
+                       init_completion(&pipe->comp);
+       printk(KERN_INFO "mdp4_overlay_pipe_alloc: pipe=%x ndx=%d\n",
+                                       (int)pipe, pipe->pipe_ndx);
+                       return pipe;
+               }
+               pipe++;
+       }
+
+       return NULL;
+}
+
+
+void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
+{
+       printk(KERN_INFO "mdp4_overlay_pipe_free: pipe=%x ndx=%d\n",
+                                       (int)pipe, pipe->pipe_ndx);
+       memset(pipe, 0, sizeof(*pipe));
+}
+
+static int get_pipe_num(int ptype, int stage)
+{
+       if (ptype == OVERLAY_TYPE_RGB) {
+               if (stage == MDP4_MIXER_STAGE_BASE)
+                       return OVERLAY_PIPE_RGB1;
+               else
+                       return OVERLAY_PIPE_RGB2;
+       } else {
+               if (stage == MDP4_MIXER_STAGE0)
+                       return OVERLAY_PIPE_VG1;
+               else
+                       return OVERLAY_PIPE_VG2;
+       }
+}
+
+int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
+{
+       struct mdp4_overlay_pipe *pipe;
+
+       pipe = ctrl->stage[mixer][z_order];
+
+       if (pipe == NULL)
+               return 0;
+
+       if (pipe->pipe_ndx == id)       /* same req, recycle */
+               return 0;
+
+       return -EPERM;
+}
+
+static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
+                       struct mdp4_overlay_pipe **ppipe)
+{
+       struct mdp4_overlay_pipe *pipe;
+       int ret, ptype;
+
+       if (mixer >= MDP4_MAX_MIXER) {
+               printk(KERN_ERR "mpd_overlay_req2pipe: mixer out of range!\n");
+               return -ERANGE;
+       }
+
+       if (req->z_order < 0 || req->z_order > 2) {
+               printk(KERN_ERR "mpd_overlay_req2pipe: z_order=%d out of range!\n",
+                               req->z_order);
+               return -ERANGE;
+       }
+
+       if (req->src_rect.h == 0 || req->src_rect.w == 0) {
+               printk(KERN_ERR "mpd_overlay_req2pipe: src img of zero size!\n");
+               return -EINVAL;
+       }
+
+       ret = mdp4_overlay_req_check(req->id, req->z_order, mixer);
+       if (ret < 0)
+               return ret;
+
+       ptype = mdp4_overlay_format2type(req->src.format);
+       if (ptype < 0)
+               return ptype;
+
+       if (req->id == MSMFB_NEW_REQUEST)  /* new request */
+               pipe = mdp4_overlay_pipe_alloc();
+       else
+               pipe = mdp4_overlay_ndx2pipe(req->id);
+
+       if (pipe == NULL)
+               return -ENOMEM;
+
+       pipe->src_format = req->src.format;
+       ret = mdp4_overlay_format2pipe(pipe);
+
+       if (ret < 0)
+               return ret;
+
+       /*
+        * base layer == 1, reserved for frame buffer
+        * zorder 0 == stage 0 == 2
+        * zorder 1 == stage 1 == 3
+        * zorder 2 == stage 2 == 4
+        */
+       if (req->id == MSMFB_NEW_REQUEST) {  /* new request */
+               pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
+               pipe->pipe_type = ptype;
+               pipe->pipe_num = get_pipe_num(ptype, pipe->mixer_stage);
+               printk(KERN_INFO "mpd4_overlay_req2pipe: zorder=%d pipe_num=%d\n",
+                               req->z_order, pipe->pipe_num);
+       }
+
+       pipe->src_width = req->src.width & 0x07ff;      /* source img width */
+       pipe->src_height = req->src.height & 0x07ff;    /* source img height */
+       pipe->src_h = req->src_rect.h & 0x07ff;
+       pipe->src_w = req->src_rect.w & 0x07ff;
+       pipe->src_y = req->src_rect.y & 0x07ff;
+       pipe->src_x = req->src_rect.x & 0x07ff;
+       pipe->dst_h = req->dst_rect.h & 0x07ff;
+       pipe->dst_w = req->dst_rect.w & 0x07ff;
+       pipe->dst_y = req->dst_rect.y & 0x07ff;
+       pipe->dst_x = req->dst_rect.x & 0x07ff;
+
+       if (req->flags & MDP_FLIP_LR)
+               pipe->op_mode |= MDP4_OP_FLIP_LR;
+
+       if (req->flags & MDP_FLIP_UD)
+               pipe->op_mode |= MDP4_OP_FLIP_UD;
+
+       if (req->flags & MDP_DITHER)
+               pipe->op_mode |= MDP4_OP_DITHER_EN;
+
+       if (req->flags & MDP_DEINTERLACE)
+               pipe->op_mode |= MDP4_OP_DEINT_ODD_REF;
+
+       pipe->is_fg = req->is_fg;/* control alpha and color key */
+
+       pipe->alpha = req->alpha & 0x0ff;
+
+       pipe->transp = req->transp_mask;
+
+       *ppipe = pipe;
+
+       return 0;
+}
+
+int get_img(struct msmfb_data *img, struct fb_info *info,
+       unsigned long *start, unsigned long *len, struct file **pp_file)
+{
+       int put_needed, ret = 0;
+       struct file *file;
+#ifdef CONFIG_ANDROID_PMEM
+       unsigned long vstart;
+#endif
+
+#ifdef CONFIG_ANDROID_PMEM
+       if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
+               return 0;
+#endif
+       file = fget_light(img->memory_id, &put_needed);
+       if (file == NULL)
+               return -1;
+
+       if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+               *start = info->fix.smem_start;
+               *len = info->fix.smem_len;
+               *pp_file = file;
+       } else {
+               ret = -1;
+               fput_light(file, put_needed);
+       }
+       return ret;
+}
+int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
+{
+       struct mdp4_overlay_pipe *pipe;
+
+       pipe = mdp4_overlay_ndx2pipe(req->id);
+       if (pipe == NULL)
+               return -ENODEV;
+
+       *req = pipe->req_data;
+
+       return 0;
+}
+
+int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       int ret, mixer;
+       struct mdp4_overlay_pipe *pipe;
+       int lcdc;
+
+       if (mfd == NULL)
+               return -ENODEV;
+
+       if (req->src.format == MDP_FB_FORMAT)
+               req->src.format = mfd->fb_imgType;
+
+       if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+               return -EINTR;
+
+       mixer = info->node; /* minor number of char device */
+
+       ret = mdp4_overlay_req2pipe(req, mixer, &pipe);
+       if (ret < 0) {
+               mutex_unlock(&mfd->dma->ov_mutex);
+               return ret;
+       }
+
+       lcdc = inpdw(MDP_BASE + 0xc0000);
+
+       if (lcdc == 0) { /* mddi */
+               /* MDP cmd block enable */
+               mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+       }
+
+       /* return id back to user */
+       req->id = pipe->pipe_ndx;       /* pipe_ndx start from 1 */
+       pipe->req_data = *req;          /* keep original req */
+
+       mutex_unlock(&mfd->dma->ov_mutex);
+
+       return 0;
+}
+
+int mdp4_overlay_unset(struct fb_info *info, int ndx)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       struct mdp4_overlay_pipe *pipe;
+       int lcdc;
+
+       if (mfd == NULL)
+               return -ENODEV;
+
+       if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+               return -EINTR;
+
+       pipe = mdp4_overlay_ndx2pipe(ndx);
+
+       if (pipe == NULL) {
+               mutex_unlock(&mfd->dma->ov_mutex);
+               return -ENODEV;
+       }
+
+       lcdc = inpdw(MDP_BASE + 0xc0000);
+
+       mdp4_mixer_stage_down(pipe);
+
+       if (lcdc == 0) { /* mddi */
+               /* MDP cmd block disable */
+               mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+       }
+
+       if (lcdc) /* LCDC mode */
+               mdp4_overlay_reg_flush(pipe, 0);
+
+       mdp4_overlay_pipe_free(pipe);
+
+       if (lcdc == 0) { /* mddi */
+               mdp4_mddi_overlay_restore();
+       }
+
+       mutex_unlock(&mfd->dma->ov_mutex);
+
+       return 0;
+}
+
+struct tile_desc {
+       uint32 width;  /* tile's width */
+       uint32 height; /* tile's height */
+       uint32 row_tile_w; /* tiles per row's width */
+       uint32 row_tile_h; /* tiles per row's height */
+};
+
+void tile_samsung(struct tile_desc *tp)
+{
+       /*
+        * each row of samsung tile consists of two tiles in height
+        * and two tiles in width which means width should align to
+        * 64 x 2 bytes and height should align to 32 x 2 bytes.
+        * video decoder generate two tiles in width and one tile
+        * in height which ends up height align to 32 X 1 bytes.
+        */
+       tp->width = 64;         /* 64 bytes */
+       tp->row_tile_w = 2;     /* 2 tiles per row's width */
+       tp->height = 32;        /* 32 bytes */
+       tp->row_tile_h = 1;     /* 1 tiles per row's height */
+}
+
+uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
+{
+       uint32 tile_w, tile_h;
+       uint32 row_num_w, row_num_h;
+
+
+       tile_w = tp->width * tp->row_tile_w;
+       tile_h = tp->height * tp->row_tile_h;
+
+       row_num_w = (pipe->src_width + tile_w - 1) / tile_w;
+       row_num_h = (pipe->src_height + tile_h - 1) / tile_h;
+
+       return row_num_w * row_num_h * tile_w * tile_h;
+}
+
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
+               struct file **pp_src_file)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       struct msmfb_data *img;
+       struct mdp4_overlay_pipe *pipe;
+       ulong start, addr;
+       ulong len = 0;
+       struct file *p_src_file = 0;
+       int lcdc;
+
+       if (mfd == NULL)
+               return -ENODEV;
+
+       pipe = mdp4_overlay_ndx2pipe(req->id);
+       if (pipe == NULL)
+               return -ENODEV;
+
+       if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+               return -EINTR;
+
+       img = &req->data;
+       get_img(img, info, &start, &len, &p_src_file);
+       if (len == 0) {
+               mutex_unlock(&mfd->dma->ov_mutex);
+               printk(KERN_ERR "mdp_overlay_play: could not retrieve"
+                                      " image from memory\n");
+               return -1;
+       }
+       *pp_src_file = p_src_file;
+
+       addr = start + img->offset;
+       pipe->srcp0_addr = addr;
+       pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
+
+       if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
+               if (pipe->frame_format == MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
+                       struct tile_desc tile;
+
+                       tile_samsung(&tile);
+                       pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile);
+               } else
+                       pipe->srcp1_addr = addr +
+                                       pipe->src_width * pipe->src_height;
+
+               pipe->srcp0_ystride = pipe->src_width;
+               pipe->srcp1_ystride = pipe->src_width;
+       }
+
+       lcdc = inpdw(MDP_BASE + 0xc0000);
+       lcdc &= 0x01; /* LCDC mode */
+
+       if (pipe->pipe_type == OVERLAY_TYPE_VG)
+               mdp4_overlay_vg_setup(pipe);    /* video/graphic pipe */
+       else
+               mdp4_overlay_rgb_setup(pipe);   /* rgb pipe */
+
+       mdp4_mixer_blend_setup(pipe);
+       mdp4_mixer_stage_up(pipe);
+
+       if (lcdc) { /* LCDC mode */
+               mdp4_overlay_reg_flush(pipe, 1);
+       }
+
+       if (lcdc) { /* LCDC mode */
+               if (pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { /* done */
+                       mutex_unlock(&mfd->dma->ov_mutex);
+                       return 0;
+               }
+       }
+
+       if (lcdc == 0) { /* MDDI mode */
+#ifdef MDP4_NONBLOCKING
+               if (mfd->panel_power_on)
+#else
+               if (!mfd->dma->busy && mfd->panel_power_on)
+#endif
+                       mdp4_mddi_overlay_kickoff(mfd, pipe);
+       }
+
+       mutex_unlock(&mfd->dma->ov_mutex);
+
+       return 0;
+}
diff --git a/drivers/staging/msm/mdp4_overlay_lcdc.c b/drivers/staging/msm/mdp4_overlay_lcdc.c
new file mode 100644 (file)
index 0000000..a6ab8ec
--- /dev/null
@@ -0,0 +1,313 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define LCDC_BASE      0xC0000
+#else
+#define LCDC_BASE      0xE0000
+#endif
+
+int first_pixel_start_x;
+int first_pixel_start_y;
+
+static struct mdp4_overlay_pipe *lcdc_pipe;
+
+int mdp_lcdc_on(struct platform_device *pdev)
+{
+       int lcdc_width;
+       int lcdc_height;
+       int lcdc_bpp;
+       int lcdc_border_clr;
+       int lcdc_underflow_clr;
+       int lcdc_hsync_skew;
+
+       int hsync_period;
+       int hsync_ctrl;
+       int vsync_period;
+       int display_hctl;
+       int display_v_start;
+       int display_v_end;
+       int active_hctl;
+       int active_h_start;
+       int active_h_end;
+       int active_v_start;
+       int active_v_end;
+       int ctrl_polarity;
+       int h_back_porch;
+       int h_front_porch;
+       int v_back_porch;
+       int v_front_porch;
+       int hsync_pulse_width;
+       int vsync_pulse_width;
+       int hsync_polarity;
+       int vsync_polarity;
+       int data_en_polarity;
+       int hsync_start_x;
+       int hsync_end_x;
+       uint8 *buf;
+       int bpp, ptype;
+       uint32 format;
+       struct fb_info *fbi;
+       struct fb_var_screeninfo *var;
+       struct msm_fb_data_type *mfd;
+       struct mdp4_overlay_pipe *pipe;
+       int ret;
+
+       mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       fbi = mfd->fbi;
+       var = &fbi->var;
+
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+       bpp = fbi->var.bits_per_pixel / 8;
+       buf = (uint8 *) fbi->fix.smem_start;
+       buf += fbi->var.xoffset * bpp +
+               fbi->var.yoffset * fbi->fix.line_length;
+
+       if (bpp == 2)
+               format = MDP_RGB_565;
+       else if (bpp == 3)
+               format = MDP_RGB_888;
+       else
+               format = MDP_ARGB_8888;
+
+
+       if (lcdc_pipe == NULL) {
+               ptype = mdp4_overlay_format2type(format);
+               pipe = mdp4_overlay_pipe_alloc();
+               pipe->pipe_type = ptype;
+               /* use RGB1 pipe */
+               pipe->pipe_num  = OVERLAY_PIPE_RGB1;
+               pipe->mixer_stage  = MDP4_MIXER_STAGE_BASE;
+               pipe->mixer_num  = MDP4_MIXER0;
+               pipe->src_format = format;
+               mdp4_overlay_format2pipe(pipe);
+
+               lcdc_pipe = pipe; /* keep it */
+       } else {
+               pipe = lcdc_pipe;
+       }
+
+       pipe->src_height = fbi->var.yres;
+       pipe->src_width = fbi->var.xres;
+       pipe->src_h = fbi->var.yres;
+       pipe->src_w = fbi->var.xres;
+       pipe->src_y = 0;
+       pipe->src_x = 0;
+       pipe->srcp0_addr = (uint32) buf;
+       pipe->srcp0_ystride = fbi->fix.line_length;
+
+       mdp4_overlay_dmap_xy(pipe);
+       mdp4_overlay_dmap_cfg(mfd, 1);
+
+       mdp4_overlay_rgb_setup(pipe);
+
+       mdp4_mixer_stage_up(pipe);
+
+       mdp4_overlayproc_cfg(pipe);
+
+       /*
+        * LCDC timing setting
+        */
+       h_back_porch = var->left_margin;
+       h_front_porch = var->right_margin;
+       v_back_porch = var->upper_margin;
+       v_front_porch = var->lower_margin;
+       hsync_pulse_width = var->hsync_len;
+       vsync_pulse_width = var->vsync_len;
+       lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
+       lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
+       lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
+
+       lcdc_width = mfd->panel_info.xres;
+       lcdc_height = mfd->panel_info.yres;
+       lcdc_bpp = mfd->panel_info.bpp;
+
+       hsync_period =
+           hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
+       hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
+       hsync_start_x = hsync_pulse_width + h_back_porch;
+       hsync_end_x = hsync_period - h_front_porch - 1;
+       display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+       vsync_period =
+           (vsync_pulse_width + v_back_porch + lcdc_height +
+            v_front_porch) * hsync_period;
+       display_v_start =
+           (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
+       display_v_end =
+           vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
+
+       if (lcdc_width != var->xres) {
+               active_h_start = hsync_start_x + first_pixel_start_x;
+               active_h_end = active_h_start + var->xres - 1;
+               active_hctl =
+                   ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
+       } else {
+               active_hctl = 0;
+       }
+
+       if (lcdc_height != var->yres) {
+               active_v_start =
+                   display_v_start + first_pixel_start_y * hsync_period;
+               active_v_end = active_v_start + (var->yres) * hsync_period - 1;
+               active_v_start |= ACTIVE_START_Y_EN;
+       } else {
+               active_v_start = 0;
+               active_v_end = 0;
+       }
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+       hsync_polarity = 1;
+       vsync_polarity = 1;
+       lcdc_underflow_clr |= 0x80000000;       /* enable recovery */
+#else
+       hsync_polarity = 0;
+       vsync_polarity = 0;
+#endif
+       data_en_polarity = 0;
+
+       ctrl_polarity =
+           (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
+
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x4, hsync_ctrl);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x8, vsync_period);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0xc, vsync_pulse_width * hsync_period);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x10, display_hctl);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x14, display_v_start);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x18, display_v_end);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x28, lcdc_border_clr);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x2c, lcdc_underflow_clr);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x30, lcdc_hsync_skew);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x38, ctrl_polarity);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x1c, active_hctl);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x20, active_v_start);
+       MDP_OUTP(MDP_BASE + LCDC_BASE + 0x24, active_v_end);
+
+       ret = panel_next_on(pdev);
+       if (ret == 0) {
+               /* enable LCDC block */
+               MDP_OUTP(MDP_BASE + LCDC_BASE, 1);
+               mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+       }
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+       return ret;
+}
+
+int mdp_lcdc_off(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct mdp4_overlay_pipe *pipe;
+
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+       MDP_OUTP(MDP_BASE + LCDC_BASE, 0);
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+       mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+       ret = panel_next_off(pdev);
+
+       /* delay to make sure the last frame finishes */
+       mdelay(100);
+
+       /* dis-engage rgb0 from mixer */
+       pipe = lcdc_pipe;
+       mdp4_mixer_stage_down(pipe);
+
+       return ret;
+}
+
+/*
+ * mdp4_overlay0_done_lcdc: called from isr
+ */
+void mdp4_overlay0_done_lcdc()
+{
+       complete(&lcdc_pipe->comp);
+}
+
+void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd)
+{
+       struct fb_info *fbi = mfd->fbi;
+       uint8 *buf;
+       int bpp;
+       unsigned long flag;
+       struct mdp4_overlay_pipe *pipe;
+
+       if (!mfd->panel_power_on)
+               return;
+
+       /* no need to power on cmd block since it's lcdc mode */
+       bpp = fbi->var.bits_per_pixel / 8;
+       buf = (uint8 *) fbi->fix.smem_start;
+       buf += fbi->var.xoffset * bpp +
+               fbi->var.yoffset * fbi->fix.line_length;
+
+       mutex_lock(&mfd->dma->ov_mutex);
+
+       pipe = lcdc_pipe;
+       pipe->srcp0_addr = (uint32) buf;
+       mdp4_overlay_rgb_setup(pipe);
+       mdp4_overlay_reg_flush(pipe, 1); /* rgb1 and mixer0 */
+
+       /* enable irq */
+       spin_lock_irqsave(&mdp_spin_lock, flag);
+       mdp_enable_irq(MDP_OVERLAY0_TERM);
+       INIT_COMPLETION(lcdc_pipe->comp);
+       mfd->dma->waiting = TRUE;
+       outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE);
+       mdp_intr_mask |= INTR_OVERLAY0_DONE;
+       outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+       spin_unlock_irqrestore(&mdp_spin_lock, flag);
+       wait_for_completion_killable(&lcdc_pipe->comp);
+       mdp_disable_irq(MDP_OVERLAY0_TERM);
+
+       mutex_unlock(&mfd->dma->ov_mutex);
+}
diff --git a/drivers/staging/msm/mdp4_overlay_mddi.c b/drivers/staging/msm/mdp4_overlay_mddi.c
new file mode 100644 (file)
index 0000000..be1b287
--- /dev/null
@@ -0,0 +1,254 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+static struct mdp4_overlay_pipe *mddi_pipe;
+static struct mdp4_overlay_pipe *pending_pipe;
+static struct msm_fb_data_type *mddi_mfd;
+
+#define WHOLESCREEN
+
+void mdp4_overlay_update_lcd(struct msm_fb_data_type *mfd)
+{
+       MDPIBUF *iBuf = &mfd->ibuf;
+       uint8 *src;
+       int bpp, ptype;
+       uint32 format;
+       uint32 mddi_ld_param;
+       uint16 mddi_vdo_packet_reg;
+       struct mdp4_overlay_pipe *pipe;
+
+       if (mfd->key != MFD_KEY)
+               return;
+
+       mddi_mfd = mfd;         /* keep it */
+
+       bpp = iBuf->bpp;
+
+       if (bpp == 2)
+               format = MDP_RGB_565;
+       else if (bpp == 3)
+               format = MDP_RGB_888;
+       else
+               format = MDP_ARGB_8888;
+
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+       if (mddi_pipe == NULL) {
+               ptype = mdp4_overlay_format2type(format);
+               pipe = mdp4_overlay_pipe_alloc();
+               pipe->pipe_type = ptype;
+               /* use RGB1 pipe */
+               pipe->pipe_num  = OVERLAY_PIPE_RGB1;
+               pipe->mixer_num  = MDP4_MIXER0;
+               pipe->src_format = format;
+               mdp4_overlay_format2pipe(pipe);
+
+               mddi_pipe = pipe; /* keep it */
+
+               mddi_ld_param = 0;
+               mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
+
+               if (mfd->panel_info.type == MDDI_PANEL) {
+                       if (mfd->panel_info.pdest == DISPLAY_1)
+                               mddi_ld_param = 0;
+                       else
+                               mddi_ld_param = 1;
+               } else {
+                       mddi_ld_param = 2;
+               }
+
+               MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
+               MDP_OUTP(MDP_BASE + 0x00094,
+                        (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+       } else {
+               pipe = mddi_pipe;
+       }
+
+
+       src = (uint8 *) iBuf->buf;
+
+#ifdef WHOLESCREEN
+       {
+               struct fb_info *fbi;
+
+               fbi = mfd->fbi;
+               pipe->src_height = fbi->var.yres;
+               pipe->src_width = fbi->var.xres;
+               pipe->src_h = fbi->var.yres;
+               pipe->src_w = fbi->var.xres;
+               pipe->src_y = 0;
+               pipe->src_x = 0;
+               pipe->dst_h = fbi->var.yres;
+               pipe->dst_w = fbi->var.xres;
+               pipe->dst_y = 0;
+               pipe->dst_x = 0;
+               pipe->srcp0_addr = (uint32)src;
+               pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
+       }
+
+#else
+       if (mdp4_overlay_active(MDP4_MIXER0)) {
+               struct fb_info *fbi;
+
+               fbi = mfd->fbi;
+               pipe->src_height = fbi->var.yres;
+               pipe->src_width = fbi->var.xres;
+               pipe->src_h = fbi->var.yres;
+               pipe->src_w = fbi->var.xres;
+               pipe->src_y = 0;
+               pipe->src_x = 0;
+               pipe->dst_h = fbi->var.yres;
+               pipe->dst_w = fbi->var.xres;
+               pipe->dst_y = 0;
+               pipe->dst_x = 0;
+               pipe->srcp0_addr = (uint32) src;
+               pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
+       } else {
+               /* starting input address */
+               src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * bpp;
+
+               pipe->src_height = iBuf->dma_h;
+               pipe->src_width = iBuf->dma_w;
+               pipe->src_h = iBuf->dma_h;
+               pipe->src_w = iBuf->dma_w;
+               pipe->src_y = 0;
+               pipe->src_x = 0;
+               pipe->dst_h = iBuf->dma_h;
+               pipe->dst_w = iBuf->dma_w;
+               pipe->dst_y = iBuf->dma_y;
+               pipe->dst_x = iBuf->dma_x;
+               pipe->srcp0_addr = (uint32) src;
+               pipe->srcp0_ystride = iBuf->ibuf_width * bpp;
+       }
+#endif
+
+       pipe->mixer_stage  = MDP4_MIXER_STAGE_BASE;
+
+       mdp4_overlay_rgb_setup(pipe);
+
+       mdp4_mixer_stage_up(pipe);
+
+       mdp4_overlayproc_cfg(pipe);
+
+       mdp4_overlay_dmap_xy(pipe);
+
+       mdp4_overlay_dmap_cfg(mfd, 0);
+
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+}
+
+/*
+ * mdp4_overlay0_done_mddi: called from isr
+ */
+void mdp4_overlay0_done_mddi()
+{
+       if (pending_pipe)
+               complete(&pending_pipe->comp);
+}
+
+void mdp4_mddi_overlay_restore(void)
+{
+       /* mutex holded by caller */
+       mdp4_overlay_update_lcd(mddi_mfd);
+       mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe);
+}
+
+void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
+                               struct mdp4_overlay_pipe *pipe)
+{
+#ifdef MDP4_NONBLOCKING
+       unsigned long flag;
+
+       spin_lock_irqsave(&mdp_spin_lock, flag);
+       if (mfd->dma->busy == TRUE) {
+               INIT_COMPLETION(pipe->comp);
+               pending_pipe = pipe;
+       }
+       spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+       if (pending_pipe != NULL) {
+               /* wait until DMA finishes the current job */
+               wait_for_completion_killable(&pipe->comp);
+               pending_pipe = NULL;
+       }
+       down(&mfd->sem);
+       mdp_enable_irq(MDP_OVERLAY0_TERM);
+       mfd->dma->busy = TRUE;
+       /* start OVERLAY pipe */
+       mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+       up(&mfd->sem);
+#else
+       down(&mfd->sem);
+       mdp_enable_irq(MDP_OVERLAY0_TERM);
+       mfd->dma->busy = TRUE;
+       INIT_COMPLETION(pipe->comp);
+       pending_pipe = pipe;
+
+       /* start OVERLAY pipe */
+       mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+       up(&mfd->sem);
+
+       /* wait until DMA finishes the current job */
+       wait_for_completion_killable(&pipe->comp);
+       mdp_disable_irq(MDP_OVERLAY0_TERM);
+#endif
+
+}
+
+void mdp4_mddi_overlay(struct msm_fb_data_type *mfd)
+{
+       mutex_lock(&mfd->dma->ov_mutex);
+
+       if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
+               mdp4_overlay_update_lcd(mfd);
+
+               mdp4_mddi_overlay_kickoff(mfd, mddi_pipe);
+
+       /* signal if pan function is waiting for the update completion */
+               if (mfd->pan_waiting) {
+                       mfd->pan_waiting = FALSE;
+                       complete(&mfd->pan_comp);
+               }
+       }
+
+       mutex_unlock(&mfd->dma->ov_mutex);
+}
diff --git a/drivers/staging/msm/mdp4_util.c b/drivers/staging/msm/mdp4_util.c
new file mode 100644 (file)
index 0000000..fd97f52
--- /dev/null
@@ -0,0 +1,1686 @@
+
+/* Copyright (c) 2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+void mdp4_sw_reset(ulong bits)
+{
+       bits &= 0x1f;   /* 5 bits */
+       outpdw(MDP_BASE + 0x001c, bits);        /* MDP_SW_RESET */
+
+       while (inpdw(MDP_BASE + 0x001c) & bits) /* self clear when complete */
+               ;
+       MSM_FB_INFO("mdp4_sw_reset: 0x%x\n", (int)bits);
+}
+
+void mdp4_overlay_cfg(int overlayer, int blt_mode, int refresh, int direct_out)
+{
+       ulong bits = 0;
+
+       if (blt_mode)
+               bits |= (1 << 3);
+       refresh &= 0x03;        /* 2 bites */
+       bits |= (refresh << 1);
+       direct_out &= 0x01;
+       bits |= direct_out;
+
+       if (overlayer == MDP4_MIXER0)
+               outpdw(MDP_BASE + 0x10004, bits); /* MDP_OVERLAY0_CFG */
+       else
+               outpdw(MDP_BASE + 0x18004, bits); /* MDP_OVERLAY1_CFG */
+
+       MSM_FB_INFO("mdp4_overlay_cfg: 0x%x\n", (int)inpdw(MDP_BASE + 0x10004));
+}
+
+void mdp4_display_intf_sel(int output, ulong intf)
+{
+       ulong bits, mask;
+
+       bits = inpdw(MDP_BASE + 0x0038);        /* MDP_DISP_INTF_SEL */
+
+       mask = 0x03;    /* 2 bits */
+       intf &= 0x03;   /* 2 bits */
+
+       switch (output) {
+       case EXTERNAL_INTF_SEL:
+               intf <<= 4;
+               mask <<= 4;
+               break;
+       case SECONDARY_INTF_SEL:
+               intf &= 0x02;   /* only MDDI and EBI2 support */
+               intf <<= 2;
+               mask <<= 2;
+               break;
+       default:
+               break;
+       }
+
+
+       bits &= ~mask;
+       bits |= intf;
+
+       outpdw(MDP_BASE + 0x0038, bits);        /* MDP_DISP_INTF_SEL */
+
+  MSM_FB_INFO("mdp4_display_intf_sel: 0x%x\n", (int)inpdw(MDP_BASE + 0x0038));
+}
+
+unsigned long mdp4_display_status(void)
+{
+       return inpdw(MDP_BASE + 0x0018) & 0x3ff;        /* MDP_DISPLAY_STATUS */
+}
+
+void mdp4_ebi2_lcd_setup(int lcd, ulong base, int ystride)
+{
+       /* always use memory map */
+       ystride &= 0x01fff;     /* 13 bits */
+       if (lcd == EBI2_LCD0) {
+               outpdw(MDP_BASE + 0x0060, base);/* MDP_EBI2_LCD0 */
+               outpdw(MDP_BASE + 0x0068, ystride);/* MDP_EBI2_LCD0_YSTRIDE */
+       } else {
+               outpdw(MDP_BASE + 0x0064, base);/* MDP_EBI2_LCD1 */
+               outpdw(MDP_BASE + 0x006c, ystride);/* MDP_EBI2_LCD1_YSTRIDE */
+       }
+}
+
+void mdp4_mddi_setup(int mddi, unsigned long id)
+{
+       ulong   bits;
+
+       if (mddi == MDDI_EXTERNAL_SET)
+               bits = 0x02;
+       else if (mddi == MDDI_SECONDARY_SET)
+               bits = 0x01;
+       else
+               bits = 0;       /* PRIMARY_SET */
+
+       id <<= 16;
+
+       bits |= id;
+
+       outpdw(MDP_BASE + 0x0090, bits); /* MDP_MDDI_PARAM_WR_SEL */
+}
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+       struct file **pp_src_file, struct file **pp_dst_file)
+{
+
+       /* not implemented yet */
+       return -1;
+}
+
+void mdp4_hw_init(void)
+{
+       ulong bits;
+
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef MDP4_ERROR
+       /*
+        * Issue software reset on DMA_P will casue DMA_P dma engine stall
+        * on LCDC mode. However DMA_P does not stall at MDDI mode.
+        * This need further investigation.
+        */
+       mdp4_sw_reset(0x17);
+#endif
+
+       mdp4_clear_lcdc();
+
+       mdp4_mixer_blend_init(0);
+       mdp4_mixer_blend_init(1);
+       mdp4_vg_qseed_init(0);
+       mdp4_vg_qseed_init(1);
+       mdp4_vg_csc_mv_setup(0);
+       mdp4_vg_csc_mv_setup(1);
+       mdp4_vg_csc_pre_bv_setup(0);
+       mdp4_vg_csc_pre_bv_setup(1);
+       mdp4_vg_csc_post_bv_setup(0);
+       mdp4_vg_csc_post_bv_setup(1);
+       mdp4_vg_csc_pre_lv_setup(0);
+       mdp4_vg_csc_pre_lv_setup(1);
+       mdp4_vg_csc_post_lv_setup(0);
+       mdp4_vg_csc_post_lv_setup(1);
+
+       mdp4_mixer_gc_lut_setup(0);
+       mdp4_mixer_gc_lut_setup(1);
+
+       mdp4_vg_igc_lut_setup(0);
+       mdp4_vg_igc_lut_setup(1);
+
+        mdp4_rgb_igc_lut_setup(0);
+        mdp4_rgb_igc_lut_setup(1);
+
+       outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
+
+       /* system interrupts */
+
+       bits =  mdp_intr_mask;
+       outpdw(MDP_BASE + 0x0050, bits);/* enable specififed interrupts */
+
+       /* histogram */
+       MDP_OUTP(MDP_BASE + 0x95010, 1);        /* auto clear HIST */
+
+       /* enable histogram interrupts */
+       outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
+
+       /* For the max read pending cmd config below, if the MDP clock     */
+       /* is less than the AXI clock, then we must use 3 pending          */
+       /* pending requests.  Otherwise, we should use 8 pending requests. */
+       /* In the future we should do this detection automatically.        */
+
+       /* max read pending cmd config */
+       outpdw(MDP_BASE + 0x004c, 0x02222);     /* 3 pending requests */
+
+       /* dma_p fetch config */
+       outpdw(MDP_BASE + 0x91004, 0x27);       /* burst size of 8 */
+
+#ifndef CONFIG_FB_MSM_OVERLAY
+       /* both REFRESH_MODE and DIRECT_OUT are ignored at BLT mode */
+       mdp4_overlay_cfg(MDP4_MIXER0, OVERLAY_MODE_BLT, 0, 0);
+       mdp4_overlay_cfg(MDP4_MIXER1, OVERLAY_MODE_BLT, 0, 0);
+#endif
+
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+
+void mdp4_clear_lcdc(void)
+{
+       uint32 bits;
+
+       bits = inpdw(MDP_BASE + 0xc0000);
+       if (bits & 0x01) /* enabled already */
+               return;
+
+       outpdw(MDP_BASE + 0xc0004, 0);  /* vsync ctrl out */
+       outpdw(MDP_BASE + 0xc0008, 0);  /* vsync period */
+       outpdw(MDP_BASE + 0xc000c, 0);  /* vsync pusle width */
+       outpdw(MDP_BASE + 0xc0010, 0);  /* lcdc display HCTL */
+       outpdw(MDP_BASE + 0xc0014, 0);  /* lcdc display v start */
+       outpdw(MDP_BASE + 0xc0018, 0);  /* lcdc display v end */
+       outpdw(MDP_BASE + 0xc001c, 0);  /* lcdc active hctl */
+       outpdw(MDP_BASE + 0xc0020, 0);  /* lcdc active v start */
+       outpdw(MDP_BASE + 0xc0024, 0);  /* lcdc active v end */
+       outpdw(MDP_BASE + 0xc0028, 0);  /* lcdc board color */
+       outpdw(MDP_BASE + 0xc002c, 0);  /* lcdc underflow ctrl */
+       outpdw(MDP_BASE + 0xc0030, 0);  /* lcdc hsync skew */
+       outpdw(MDP_BASE + 0xc0034, 0);  /* lcdc test ctl */
+       outpdw(MDP_BASE + 0xc0038, 0);  /* lcdc ctl polarity */
+}
+
+static struct mdp_dma_data overlay1_data;
+static int intr_dma_p;
+static int intr_dma_s;
+static int intr_dma_e;
+static int intr_overlay0;
+static int intr_overlay1;
+
+irqreturn_t mdp4_isr(int irq, void *ptr)
+{
+       uint32 isr, mask, lcdc;
+       struct mdp_dma_data *dma;
+
+       mdp_is_in_isr = TRUE;
+
+       while (1) {
+               isr = inpdw(MDP_INTR_STATUS);
+               if (isr == 0)
+                       break;
+
+               mask = inpdw(MDP_INTR_ENABLE);
+               outpdw(MDP_INTR_CLEAR, isr);
+
+               isr &= mask;
+
+               if (unlikely(isr == 0))
+                       break;
+
+               if (isr & INTR_DMA_P_DONE) {
+                       intr_dma_p++;
+                       lcdc = inpdw(MDP_BASE + 0xc0000);
+                       dma = &dma2_data;
+                       if (lcdc & 0x01) {      /* LCDC enable */
+                               /* disable LCDC interrupt */
+                               mdp_intr_mask &= ~INTR_DMA_P_DONE;
+                               outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+                               dma->waiting = FALSE;
+                       } else {
+                               dma->busy = FALSE;
+                               mdp_pipe_ctrl(MDP_DMA2_BLOCK,
+                                       MDP_BLOCK_POWER_OFF, TRUE);
+                       }
+                       complete(&dma->comp);
+               }
+               if (isr & INTR_DMA_S_DONE) {
+                       intr_dma_s++;
+                       dma = &dma_s_data;
+                       dma->busy = FALSE;
+                       mdp_pipe_ctrl(MDP_DMA_S_BLOCK,
+                                       MDP_BLOCK_POWER_OFF, TRUE);
+                       complete(&dma->comp);
+               }
+               if (isr & INTR_DMA_E_DONE) {
+                       intr_dma_e++;
+                       dma = &dma_e_data;
+                       mdp_intr_mask &= ~INTR_DMA_E_DONE;
+                       outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+                       dma->busy = FALSE;
+
+                       if (dma->waiting) {
+                               dma->waiting = FALSE;
+                               complete(&dma->comp);
+                       }
+               }
+               if (isr & INTR_OVERLAY0_DONE) {
+                       intr_overlay0++;
+                       lcdc = inpdw(MDP_BASE + 0xc0000);
+                       dma = &dma2_data;
+                       if (lcdc & 0x01) {      /* LCDC enable */
+                               /* disable LCDC interrupt */
+                               mdp_intr_mask &= ~INTR_OVERLAY0_DONE;
+                               outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+                               dma->waiting = FALSE;
+                               mdp4_overlay0_done_lcdc();
+                       } else {        /* MDDI */
+                               dma->busy = FALSE;
+#ifdef MDP4_NONBLOCKING
+                               mdp_disable_irq_nolock(MDP_OVERLAY0_TERM);
+#endif
+                               mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK,
+                                       MDP_BLOCK_POWER_OFF, TRUE);
+                               mdp4_overlay0_done_mddi();
+                       }
+               }
+               if (isr & INTR_OVERLAY1_DONE) {
+                       intr_overlay1++;
+                       dma = &overlay1_data;
+                       dma->busy = FALSE;
+                       mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK,
+                                       MDP_BLOCK_POWER_OFF, TRUE);
+                       complete(&dma->comp);
+               }
+               if (isr & INTR_DMA_P_HISTOGRAM) {
+                       isr = inpdw(MDP_DMA_P_HIST_INTR_STATUS);
+                       mask = inpdw(MDP_DMA_P_HIST_INTR_ENABLE);
+                       outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr);
+                       isr &= mask;
+                       if (isr & INTR_HIST_DONE) {
+                               if (mdp_hist.r)
+                                       memcpy(mdp_hist.r, MDP_BASE + 0x95100,
+                                                       mdp_hist.bin_cnt*4);
+                               if (mdp_hist.g)
+                                       memcpy(mdp_hist.g, MDP_BASE + 0x95200,
+                                                       mdp_hist.bin_cnt*4);
+                               if (mdp_hist.b)
+                                       memcpy(mdp_hist.b, MDP_BASE + 0x95300,
+                                               mdp_hist.bin_cnt*4);
+                               complete(&mdp_hist_comp);
+                       }
+               }
+       }
+
+       mdp_is_in_isr = FALSE;
+
+       return IRQ_HANDLED;
+}
+
+
+/*
+ * QSEED tables
+ */
+
+static uint32 vg_qseed_table0[] = {
+       0x5556aaff, 0x00000000, 0x00000000, 0x00000000
+};
+
+static uint32 vg_qseed_table1[] = {
+       0x76543210, 0xfedcba98
+};
+
+static uint32 vg_qseed_table2[] = {
+       0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
+       0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
+       0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
+       0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
+       0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
+       0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
+       0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
+       0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
+       0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
+       0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
+       0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
+       0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
+       0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
+       0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
+       0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
+       0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
+       0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
+       0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
+       0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
+       0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
+       0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
+       0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
+       0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
+       0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
+       0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
+       0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
+       0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
+       0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
+       0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
+       0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
+       0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
+       0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
+       0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
+       0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
+       0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
+       0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
+       0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
+       0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
+       0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
+       0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
+       0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
+       0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
+       0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
+       0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
+       0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
+       0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
+       0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
+       0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
+       0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
+       0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
+       0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
+       0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
+       0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
+       0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
+       0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
+       0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
+       0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
+       0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
+       0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
+       0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
+       0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
+       0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
+       0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
+       0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
+       0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
+       0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
+       0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
+       0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
+       0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
+       0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
+       0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
+       0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
+       0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
+       0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
+       0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
+       0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
+       0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
+       0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
+       0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
+       0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
+       0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
+       0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
+       0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
+       0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
+       0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
+       0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
+       0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
+       0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
+       0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
+       0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
+       0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
+       0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
+       0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
+       0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
+       0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
+       0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
+       0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
+       0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
+       0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
+       0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
+       0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
+       0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
+       0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
+       0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
+       0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
+       0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
+       0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
+       0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
+       0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
+       0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
+       0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
+       0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
+       0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
+       0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
+       0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
+       0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
+       0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
+       0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
+       0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
+       0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
+       0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
+       0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
+       0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
+       0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
+       0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
+       0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
+       0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
+       0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
+       0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
+       0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
+       0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
+       0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
+       0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
+       0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
+       0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
+       0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
+       0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
+       0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
+       0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
+       0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
+       0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
+       0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
+       0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
+       0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
+       0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
+       0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
+       0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
+       0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
+       0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
+       0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
+       0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
+       0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
+       0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
+       0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
+       0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
+       0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
+       0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
+       0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
+       0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
+       0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
+       0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
+       0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
+       0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
+       0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
+       0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
+       0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
+       0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
+       0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
+       0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
+       0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
+       0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
+       0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
+       0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
+       0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
+       0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
+       0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
+       0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
+       0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
+       0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
+       0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
+       0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
+       0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
+       0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
+       0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
+       0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
+       0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
+       0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
+       0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
+       0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
+       0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
+       0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
+       0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
+       0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
+       0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
+       0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
+       0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
+       0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
+       0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
+       0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
+       0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
+       0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
+       0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
+       0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
+       0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
+       0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
+       0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
+       0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
+       0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
+       0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
+       0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
+       0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
+       0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
+       0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
+       0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
+       0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
+       0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
+       0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
+       0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
+       0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
+       0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
+       0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
+       0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
+       0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
+       0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
+       0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
+       0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
+       0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
+       0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
+       0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
+       0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
+       0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
+       0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
+       0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
+       0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
+       0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
+       0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
+       0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
+       0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
+       0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
+       0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
+       0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
+       0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
+       0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
+       0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
+       0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
+       0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
+       0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
+       0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
+       0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
+       0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
+       0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
+       0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
+       0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
+       0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
+       0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
+       0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff,
+       0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
+       0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
+       0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
+       0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
+       0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
+       0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
+       0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
+       0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
+       0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
+       0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
+       0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
+       0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
+       0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
+       0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
+       0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
+       0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
+       0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
+       0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
+       0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
+       0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
+       0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
+       0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
+       0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
+       0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
+       0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
+       0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
+       0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
+       0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
+       0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
+       0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
+       0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
+       0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
+       0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
+       0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
+       0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
+       0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
+       0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
+       0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
+       0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
+       0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
+       0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
+       0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
+       0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
+       0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
+       0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
+       0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
+       0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
+       0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
+       0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
+       0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
+       0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
+       0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
+       0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
+       0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
+       0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
+       0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
+       0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
+       0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
+       0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
+       0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
+       0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
+       0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
+       0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
+       0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
+       0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
+       0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
+       0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
+       0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
+       0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
+       0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
+       0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
+       0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
+       0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
+       0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
+       0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
+       0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
+       0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
+       0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
+       0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
+       0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
+       0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
+       0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
+       0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
+       0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
+       0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
+       0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
+       0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
+       0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
+       0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
+       0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
+       0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
+       0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
+       0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
+       0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
+       0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
+       0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
+       0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
+       0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
+       0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
+       0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
+       0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
+       0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
+       0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
+       0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
+       0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
+       0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
+       0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
+       0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
+       0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
+       0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
+       0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
+       0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
+       0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
+       0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
+       0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
+       0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
+       0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
+       0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
+       0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
+       0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
+       0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
+       0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
+       0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
+       0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
+       0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
+       0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
+       0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
+       0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
+       0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
+       0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
+       0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
+       0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
+       0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
+       0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
+       0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
+       0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
+       0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
+       0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
+       0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
+       0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
+       0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
+       0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
+       0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
+       0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
+       0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
+       0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
+       0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
+       0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
+       0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
+       0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
+       0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
+       0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
+       0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
+       0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
+       0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
+       0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
+       0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
+       0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
+       0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
+       0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
+       0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
+       0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
+       0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
+       0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
+       0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
+       0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
+       0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
+       0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
+       0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
+       0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
+       0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
+       0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
+       0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
+       0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
+       0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
+       0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
+       0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
+       0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
+       0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
+       0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
+       0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
+       0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
+       0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
+       0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
+       0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
+       0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
+       0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
+       0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
+       0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
+       0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
+       0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
+       0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
+       0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
+       0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
+       0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
+       0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
+       0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
+       0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
+       0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
+       0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
+       0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
+       0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
+       0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
+       0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
+       0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
+       0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
+       0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
+       0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
+       0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
+       0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
+       0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
+       0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
+       0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
+       0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
+       0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
+       0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
+       0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
+       0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
+       0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
+       0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
+       0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
+       0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
+       0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
+       0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
+       0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
+       0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
+       0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
+       0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
+       0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
+       0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
+       0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
+       0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
+       0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
+       0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
+       0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
+       0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
+       0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
+       0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
+       0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
+       0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
+       0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
+       0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
+       0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
+       0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
+       0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
+       0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
+       0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
+       0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
+       0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
+       0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
+       0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
+       0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
+       0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
+       0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
+       0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
+       0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff
+};
+
+
+#define MDP4_QSEED_TABLE0_OFF 0x8100
+#define MDP4_QSEED_TABLE1_OFF 0x8200
+#define MDP4_QSEED_TABLE2_OFF 0x9000
+
+void mdp4_vg_qseed_init(int vp_num)
+{
+       uint32 *off;
+       int i, voff;
+
+       voff = MDP4_VIDEO_OFF * vp_num;
+       off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+                                               MDP4_QSEED_TABLE0_OFF);
+       for (i = 0; i < (sizeof(vg_qseed_table0) / sizeof(uint32)); i++) {
+               outpdw(off, vg_qseed_table0[i]);
+               off++;
+       }
+
+       off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+                                               MDP4_QSEED_TABLE1_OFF);
+       for (i = 0; i < (sizeof(vg_qseed_table1) / sizeof(uint32)); i++) {
+               outpdw(off, vg_qseed_table1[i]);
+               off++;
+       }
+
+       off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+                                               MDP4_QSEED_TABLE2_OFF);
+       for (i = 0; i < (sizeof(vg_qseed_table2) / sizeof(uint32)); i++) {
+               outpdw(off, vg_qseed_table2[i]);
+               off++;
+       }
+
+}
+
+void mdp4_mixer_blend_init(mixer_num)
+{
+       unsigned char *overlay_base;
+       int off;
+
+       if (mixer_num)  /* mixer number, /dev/fb0, /dev/fb1 */
+               overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+       else
+               overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+       /* stage 0 to stage 2 */
+       off = 0;
+       outpdw(overlay_base + off + 0x104, 0x010);
+       outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+       outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+
+       off += 0x20;
+       outpdw(overlay_base + off + 0x104, 0x010);
+       outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+       outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+
+       off += 0x20;
+       outpdw(overlay_base + off + 0x104, 0x010);
+       outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+       outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+}
+
+
+static uint32 csc_matrix_tab[9] = {
+       0x0254, 0x0000, 0x0331,
+       0x0254, 0xff37, 0xfe60,
+       0x0254, 0x0409, 0x0000
+};
+
+static uint32 csc_pre_bv_tab[3] = {0xfff0, 0xff80, 0xff80 };
+static uint32 csc_post_bv_tab[3] = {0, 0, 0 };
+
+static  uint32 csc_pre_lv_tab[6] =  {0, 0xff, 0, 0xff, 0, 0xff };
+static  uint32 csc_post_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
+
+#define MDP4_CSC_MV_OFF        0x4400
+#define MDP4_CSC_PRE_BV_OFF    0x4500
+#define MDP4_CSC_POST_BV_OFF   0x4580
+#define MDP4_CSC_PRE_LV_OFF    0x4600
+#define MDP4_CSC_POST_LV_OFF   0x4680
+
+void mdp4_vg_csc_mv_setup(int vp_num)
+{
+       uint32 *off;
+       int i, voff;
+
+       voff = MDP4_VIDEO_OFF * vp_num;
+       off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+                                       MDP4_CSC_MV_OFF);
+       for (i = 0; i < 9; i++) {
+               outpdw(off, csc_matrix_tab[i]);
+               off++;
+       }
+}
+
+void mdp4_vg_csc_pre_bv_setup(int vp_num)
+{
+       uint32 *off;
+       int i, voff;
+
+       voff = MDP4_VIDEO_OFF * vp_num;
+       off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+                                       MDP4_CSC_PRE_BV_OFF);
+       for (i = 0; i < 3; i++) {
+               outpdw(off, csc_pre_bv_tab[i]);
+               off++;
+       }
+}
+
+void mdp4_vg_csc_post_bv_setup(int vp_num)
+{
+       uint32 *off;
+       int i, voff;
+
+       voff = MDP4_VIDEO_OFF * vp_num;
+       off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+                                       MDP4_CSC_POST_BV_OFF);
+       for (i = 0; i < 3; i++) {
+               outpdw(off, csc_post_bv_tab[i]);
+               off++;
+       }
+}
+
+void mdp4_vg_csc_pre_lv_setup(int vp_num)
+{
+       uint32 *off;
+       int i, voff;
+
+       voff = MDP4_VIDEO_OFF * vp_num;
+       off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+                                       MDP4_CSC_PRE_LV_OFF);
+
+       for (i = 0; i < 6; i++) {
+               outpdw(off, csc_pre_lv_tab[i]);
+               off++;
+       }
+}
+
+void mdp4_vg_csc_post_lv_setup(int vp_num)
+{
+       uint32 *off;
+       int i, voff;
+
+       voff = MDP4_VIDEO_OFF * vp_num;
+       off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+                                       MDP4_CSC_POST_LV_OFF);
+
+       for (i = 0; i < 6; i++) {
+               outpdw(off, csc_post_lv_tab[i]);
+               off++;
+       }
+}
+
+char gc_lut[] = {
+       0x0, 0x1, 0x2, 0x2, 0x3, 0x4, 0x5, 0x6,
+       0x6, 0x7, 0x8, 0x9, 0xA, 0xA, 0xB, 0xC,
+       0xD, 0xD, 0xE, 0xF, 0xF, 0x10, 0x10, 0x11,
+       0x12, 0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15,
+       0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x19,
+       0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C,
+       0x1C, 0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F,
+       0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21,
+       0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24,
+       0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26,
+       0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28,
+       0x28, 0x29, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A,
+       0x2A, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C,
+       0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E,
+       0x2E, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x2F, 0x30,
+       0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
+       0x31, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33,
+       0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34,
+       0x35, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36,
+       0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
+       0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39,
+       0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A,
+       0x3A, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3C,
+       0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D,
+       0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E,
+       0x3E, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x40,
+       0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41,
+       0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42,
+       0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43,
+       0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+       0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
+       0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47,
+       0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48,
+       0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49,
+       0x49, 0x49, 0x49, 0x49, 0x49, 0x4A, 0x4A, 0x4A,
+       0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4B,
+       0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C,
+       0x4C, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4D,
+       0x4D, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4E, 0x4E,
+       0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4F, 0x4F, 0x4F,
+       0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x50, 0x50, 0x50,
+       0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51,
+       0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
+       0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53,
+       0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54,
+       0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
+       0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+       0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
+       0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+       0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58,
+       0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59,
+       0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5A, 0x5A,
+       0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+       0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B,
+       0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+       0x5C, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5D, 0x5D,
+       0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E,
+       0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E,
+       0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F,
+       0x5F, 0x5F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
+       0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+       0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x62,
+       0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62,
+       0x62, 0x62, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64,
+       0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+       0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
+       0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66,
+       0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67,
+       0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67,
+       0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
+       0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
+       0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+       0x69, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
+       0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B, 0x6B,
+       0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B,
+       0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C,
+       0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D,
+       0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+       0x6D, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E,
+       0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F,
+       0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F,
+       0x6F, 0x6F, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
+       0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71,
+       0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
+       0x71, 0x71, 0x71, 0x72, 0x72, 0x72, 0x72, 0x72,
+       0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+       0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+       0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
+       0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74,
+       0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
+       0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
+       0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+       0x76, 0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77,
+       0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+       0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78, 0x78,
+       0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+       0x78, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
+       0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x7A, 0x7A,
+       0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A,
+       0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7B,
+       0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B,
+       0x7B, 0x7B, 0x7B, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
+       0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
+       0x7C, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
+       0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
+       0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E,
+       0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F,
+       0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+       0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x80, 0x80,
+       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+       0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
+       0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+       0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82,
+       0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
+       0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+       0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+       0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
+       0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
+       0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+       0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+       0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
+       0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
+       0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
+       0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
+       0x87, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+       0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+       0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+       0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+       0x89, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
+       0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
+       0x8A, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
+       0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
+       0x8B, 0x8B, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
+       0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
+       0x8C, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
+       0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
+       0x8D, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8E,
+       0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E,
+       0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F,
+       0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F,
+       0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x90, 0x90,
+       0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+       0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x91,
+       0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+       0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+       0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+       0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+       0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+       0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+       0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+       0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+       0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95,
+       0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+       0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+       0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
+       0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
+       0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97,
+       0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
+       0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+       0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+       0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+       0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
+       0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
+       0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+       0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+       0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0x9B, 0x9B,
+       0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
+       0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
+       0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
+       0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
+       0x9C, 0x9C, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9D,
+       0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D,
+       0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9E,
+       0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+       0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+       0x9E, 0x9E, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
+       0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
+       0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0xA0, 0xA0,
+       0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+       0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+       0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+       0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+       0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA2, 0xA2,
+       0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
+       0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
+       0xA2, 0xA2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
+       0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
+       0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA4, 0xA4,
+       0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+       0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+       0xA4, 0xA4, 0xA4, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+       0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+       0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+       0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
+       0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
+       0xA6, 0xA6, 0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA7,
+       0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
+       0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
+       0xA7, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
+       0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
+       0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA9,
+       0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
+       0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
+       0xA9, 0xA9, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAA,
+       0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+       0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+       0xAA, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+       0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+       0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAC,
+       0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+       0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+       0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAD, 0xAD, 0xAD,
+       0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
+       0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
+       0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+       0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+       0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+       0xAE, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
+       0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
+       0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xB0,
+       0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
+       0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
+       0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB1,
+       0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
+       0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
+       0xB1, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB2, 0xB2,
+       0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
+       0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
+       0xB2, 0xB2, 0xB2, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+       0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+       0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+       0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+       0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+       0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+       0xB4, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+       0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+       0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+       0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+       0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+       0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+       0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
+       0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
+       0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB8,
+       0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
+       0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
+       0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB9,
+       0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+       0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+       0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xBA,
+       0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
+       0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
+       0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBB,
+       0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+       0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+       0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+       0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+       0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+       0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+       0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+       0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+       0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+       0xBD, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+       0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+       0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+       0xBE, 0xBE, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+       0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+       0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+       0xBF, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+       0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+       0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+       0xC0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC1, 0xC1, 0xC1,
+       0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
+       0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
+       0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC2, 0xC2, 0xC2,
+       0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
+       0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
+       0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC3, 0xC3,
+       0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+       0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+       0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+       0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+       0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+       0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+       0xC4, 0xC4, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+       0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+       0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+       0xC5, 0xC5, 0xC5, 0xC5, 0xC6, 0xC6, 0xC6, 0xC6,
+       0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+       0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+       0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, 0xC7,
+       0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+       0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+       0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+       0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+       0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+       0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+       0xC8, 0xC8, 0xC8, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+       0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+       0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+       0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xCA, 0xCA,
+       0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+       0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+       0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+       0xCA, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+       0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+       0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+       0xCB, 0xCB, 0xCB, 0xCB, 0xCC, 0xCC, 0xCC, 0xCC,
+       0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
+       0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
+       0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD,
+       0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+       0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+       0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+       0xCD, 0xCD, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+       0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+       0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+       0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCF, 0xCF,
+       0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+       0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+       0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+       0xCF, 0xCF, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+       0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+       0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+       0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD1, 0xD1, 0xD1,
+       0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+       0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+       0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+       0xD1, 0xD1, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+       0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+       0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+       0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD3, 0xD3,
+       0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+       0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+       0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+       0xD3, 0xD3, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+       0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+       0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+       0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD5,
+       0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+       0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+       0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+       0xD5, 0xD5, 0xD5, 0xD5, 0xD6, 0xD6, 0xD6, 0xD6,
+       0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+       0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+       0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+       0xD6, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+       0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+       0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+       0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD8, 0xD8,
+       0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+       0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+       0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+       0xD8, 0xD8, 0xD8, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+       0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+       0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+       0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+       0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+       0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+       0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+       0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDB, 0xDB,
+       0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+       0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+       0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+       0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC,
+       0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+       0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+       0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+       0xDC, 0xDC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+       0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+       0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+       0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+       0xDD, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+       0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+       0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+       0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDF,
+       0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+       0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+       0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+       0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xE0, 0xE0,
+       0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+       0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+       0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+       0xE0, 0xE0, 0xE0, 0xE0, 0xE1, 0xE1, 0xE1, 0xE1,
+       0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+       0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+       0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+       0xE1, 0xE1, 0xE1, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+       0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+       0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+       0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+       0xE2, 0xE2, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+       0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+       0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+       0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+       0xE3, 0xE3, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+       0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+       0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+       0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+       0xE4, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+       0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+       0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+       0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+       0xE5, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+       0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+       0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+       0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+       0xE6, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+       0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+       0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+       0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+       0xE7, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+       0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+       0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+       0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+       0xE8, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+       0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+       0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+       0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+       0xE9, 0xE9, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+       0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+       0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+       0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+       0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+       0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+       0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+       0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+       0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+       0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+       0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+       0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+       0xEC, 0xEC, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xED,
+       0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+       0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+       0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+       0xED, 0xED, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE,
+       0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+       0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+       0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+       0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF,
+       0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+       0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+       0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+       0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+       0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+       0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+       0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+       0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+       0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+       0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+       0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+       0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+       0xF1, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF2, 0xF2,
+       0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+       0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+       0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+       0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3,
+       0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+       0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+       0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+       0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+       0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+       0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+       0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+       0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+       0xF4, 0xF4, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+       0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+       0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+       0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+       0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6,
+       0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+       0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+       0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+       0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+       0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+       0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+       0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+       0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+       0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+       0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+       0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+       0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+       0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9,
+       0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+       0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+       0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+       0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+       0xF9, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+       0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+       0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+       0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+       0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB,
+       0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+       0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+       0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+       0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+       0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+       0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+       0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+       0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+       0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD,
+       0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+       0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+       0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+       0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+       0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+       0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+       0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+       0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+       0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+void mdp4_mixer_gc_lut_setup(int mixer_num)
+{
+       unsigned char *base;
+       uint32 data;
+       char val;
+       int i, off;
+
+       if (mixer_num)  /* mixer number, /dev/fb0, /dev/fb1 */
+               base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+       else
+               base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+       base += 0x4000; /* GC_LUT offset */
+
+       off = 0;
+       for (i = 0; i < 4096; i++) {
+               val = gc_lut[i];
+               data = (val << 16 | val << 8 | val); /* R, B, and G are same */
+               outpdw(base + off, data);
+               off += 4;
+       }
+}
+
+uint32 igc_video_lut[] = {      /* non linear */
+       0x0, 0x1, 0x2, 0x4, 0x5, 0x6, 0x7, 0x9,
+       0xA, 0xB, 0xC, 0xE, 0xF, 0x10, 0x12, 0x14,
+       0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23,
+       0x25, 0x28, 0x2A, 0x2D, 0x30, 0x32, 0x35, 0x38,
+       0x3B, 0x3E, 0x42, 0x45, 0x48, 0x4C, 0x4F, 0x53,
+       0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x70, 0x74,
+       0x79, 0x7E, 0x83, 0x88, 0x8D, 0x92, 0x97, 0x9C,
+       0xA2, 0xA8, 0xAD, 0xB3, 0xB9, 0xBF, 0xC5, 0xCC,
+       0xD2, 0xD8, 0xDF, 0xE6, 0xED, 0xF4, 0xFB, 0x102,
+       0x109, 0x111, 0x118, 0x120, 0x128, 0x130, 0x138, 0x140,
+       0x149, 0x151, 0x15A, 0x162, 0x16B, 0x174, 0x17D, 0x186,
+       0x190, 0x199, 0x1A3, 0x1AC, 0x1B6, 0x1C0, 0x1CA, 0x1D5,
+       0x1DF, 0x1EA, 0x1F4, 0x1FF, 0x20A, 0x215, 0x220, 0x22B,
+       0x237, 0x242, 0x24E, 0x25A, 0x266, 0x272, 0x27F, 0x28B,
+       0x298, 0x2A4, 0x2B1, 0x2BE, 0x2CB, 0x2D8, 0x2E6, 0x2F3,
+       0x301, 0x30F, 0x31D, 0x32B, 0x339, 0x348, 0x356, 0x365,
+       0x374, 0x383, 0x392, 0x3A1, 0x3B1, 0x3C0, 0x3D0, 0x3E0,
+       0x3F0, 0x400, 0x411, 0x421, 0x432, 0x443, 0x454, 0x465,
+       0x476, 0x487, 0x499, 0x4AB, 0x4BD, 0x4CF, 0x4E1, 0x4F3,
+       0x506, 0x518, 0x52B, 0x53E, 0x551, 0x565, 0x578, 0x58C,
+       0x5A0, 0x5B3, 0x5C8, 0x5DC, 0x5F0, 0x605, 0x61A, 0x62E,
+       0x643, 0x659, 0x66E, 0x684, 0x699, 0x6AF, 0x6C5, 0x6DB,
+       0x6F2, 0x708, 0x71F, 0x736, 0x74D, 0x764, 0x77C, 0x793,
+       0x7AB, 0x7C3, 0x7DB, 0x7F3, 0x80B, 0x824, 0x83D, 0x855,
+       0x86F, 0x888, 0x8A1, 0x8BB, 0x8D4, 0x8EE, 0x908, 0x923,
+       0x93D, 0x958, 0x973, 0x98E, 0x9A9, 0x9C4, 0x9DF, 0x9FB,
+       0xA17, 0xA33, 0xA4F, 0xA6C, 0xA88, 0xAA5, 0xAC2, 0xADF,
+       0xAFC, 0xB19, 0xB37, 0xB55, 0xB73, 0xB91, 0xBAF, 0xBCE,
+       0xBEC, 0xC0B, 0xC2A, 0xC4A, 0xC69, 0xC89, 0xCA8, 0xCC8,
+       0xCE8, 0xD09, 0xD29, 0xD4A, 0xD6B, 0xD8C, 0xDAD, 0xDCF,
+       0xDF0, 0xE12, 0xE34, 0xE56, 0xE79, 0xE9B, 0xEBE, 0xEE1,
+       0xF04, 0xF27, 0xF4B, 0xF6E, 0xF92, 0xFB6, 0xFDB, 0xFFF,
+};
+
+void mdp4_vg_igc_lut_setup(int vp_num)
+{
+       unsigned char *base;
+       int i, voff, off;
+       uint32 data, val;
+
+       voff = MDP4_VIDEO_OFF * vp_num;
+       base = MDP_BASE + MDP4_VIDEO_BASE + voff + 0x5000;
+
+       off = 0;
+       for (i = 0; i < 256; i++) {
+               val = igc_video_lut[i];
+               data = (val << 16 | val);       /* color 0 and 1 */
+               outpdw(base + off, data);
+               outpdw(base + off + 0x800, val);        /* color 2 */
+               off += 4;
+       }
+}
+
+uint32 igc_rgb_lut[] = {   /* linear */
+       0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
+       0x80, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
+       0x101, 0x111, 0x121, 0x131, 0x141, 0x151, 0x161, 0x171,
+       0x181, 0x191, 0x1A2, 0x1B2, 0x1C2, 0x1D2, 0x1E2, 0x1F2,
+       0x202, 0x212, 0x222, 0x232, 0x242, 0x252, 0x262, 0x272,
+       0x282, 0x292, 0x2A2, 0x2B3, 0x2C3, 0x2D3, 0x2E3, 0x2F3,
+       0x303, 0x313, 0x323, 0x333, 0x343, 0x353, 0x363, 0x373,
+       0x383, 0x393, 0x3A3, 0x3B3, 0x3C4, 0x3D4, 0x3E4, 0x3F4,
+       0x404, 0x414, 0x424, 0x434, 0x444, 0x454, 0x464, 0x474,
+       0x484, 0x494, 0x4A4, 0x4B4, 0x4C4, 0x4D5, 0x4E5, 0x4F5,
+       0x505, 0x515, 0x525, 0x535, 0x545, 0x555, 0x565, 0x575,
+       0x585, 0x595, 0x5A5, 0x5B5, 0x5C5, 0x5D5, 0x5E6, 0x5F6,
+       0x606, 0x616, 0x626, 0x636, 0x646, 0x656, 0x666, 0x676,
+       0x686, 0x696, 0x6A6, 0x6B6, 0x6C6, 0x6D6, 0x6E6, 0x6F7,
+       0x707, 0x717, 0x727, 0x737, 0x747, 0x757, 0x767, 0x777,
+       0x787, 0x797, 0x7A7, 0x7B7, 0x7C7, 0x7D7, 0x7E7, 0x7F7,
+       0x808, 0x818, 0x828, 0x838, 0x848, 0x858, 0x868, 0x878,
+       0x888, 0x898, 0x8A8, 0x8B8, 0x8C8, 0x8D8, 0x8E8, 0x8F8,
+       0x908, 0x919, 0x929, 0x939, 0x949, 0x959, 0x969, 0x979,
+       0x989, 0x999, 0x9A9, 0x9B9, 0x9C9, 0x9D9, 0x9E9, 0x9F9,
+       0xA09, 0xA19, 0xA2A, 0xA3A, 0xA4A, 0xA5A, 0xA6A, 0xA7A,
+       0xA8A, 0xA9A, 0xAAA, 0xABA, 0xACA, 0xADA, 0xAEA, 0xAFA,
+       0xB0A, 0xB1A, 0xB2A, 0xB3B, 0xB4B, 0xB5B, 0xB6B, 0xB7B,
+       0xB8B, 0xB9B, 0xBAB, 0xBBB, 0xBCB, 0xBDB, 0xBEB, 0xBFB,
+       0xC0B, 0xC1B, 0xC2B, 0xC3B, 0xC4C, 0xC5C, 0xC6C, 0xC7C,
+       0xC8C, 0xC9C, 0xCAC, 0xCBC, 0xCCC, 0xCDC, 0xCEC, 0xCFC,
+       0xD0C, 0xD1C, 0xD2C, 0xD3C, 0xD4C, 0xD5D, 0xD6D, 0xD7D,
+       0xD8D, 0xD9D, 0xDAD, 0xDBD, 0xDCD, 0xDDD, 0xDED, 0xDFD,
+       0xE0D, 0xE1D, 0xE2D, 0xE3D, 0xE4D, 0xE5D, 0xE6E, 0xE7E,
+       0xE8E, 0xE9E, 0xEAE, 0xEBE, 0xECE, 0xEDE, 0xEEE, 0xEFE,
+       0xF0E, 0xF1E, 0xF2E, 0xF3E, 0xF4E, 0xF5E, 0xF6E, 0xF7F,
+       0xF8F, 0xF9F, 0xFAF, 0xFBF, 0xFCF, 0xFDF, 0xFEF, 0xFFF,
+};
+
+void mdp4_rgb_igc_lut_setup(int num)
+{
+       unsigned char *base;
+       int i, voff, off;
+       uint32 data, val;
+
+       voff = MDP4_RGB_OFF * num;
+       base = MDP_BASE + MDP4_RGB_BASE + voff + 0x5000;
+
+       off = 0;
+       for (i = 0; i < 256; i++) {
+               val = igc_rgb_lut[i];
+               data = (val << 16 | val);       /* color 0 and 1 */
+               outpdw(base + off, data);
+               outpdw(base + off + 0x800, val);        /* color 2 */
+               off += 4;
+       }
+}
diff --git a/drivers/staging/msm/mdp_cursor.c b/drivers/staging/msm/mdp_cursor.c
new file mode 100644 (file)
index 0000000..7d28f30
--- /dev/null
@@ -0,0 +1,104 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static int cursor_enabled;
+
+int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       struct fb_image *img = &cursor->image;
+       int calpha_en, transp_en;
+       int alpha;
+       int ret = 0;
+
+       if ((img->width > MDP_CURSOR_WIDTH) ||
+           (img->height > MDP_CURSOR_HEIGHT) ||
+           (img->depth != 32))
+               return -EINVAL;
+
+       if (cursor->set & FB_CUR_SETPOS)
+               MDP_OUTP(MDP_BASE + 0x9004c, (img->dy << 16) | img->dx);
+
+       if (cursor->set & FB_CUR_SETIMAGE) {
+               ret = copy_from_user(mfd->cursor_buf, img->data,
+                                       img->width*img->height*4);
+               if (ret)
+                       return ret;
+
+               if (img->bg_color == 0xffffffff)
+                       transp_en = 0;
+               else
+                       transp_en = 1;
+
+               alpha = (img->fg_color & 0xff000000) >> 24;
+
+               if (alpha)
+                       calpha_en = 0x2; /* xrgb */
+               else
+                       calpha_en = 0x1; /* argb */
+
+               MDP_OUTP(MDP_BASE + 0x90044, (img->height << 16) | img->width);
+               MDP_OUTP(MDP_BASE + 0x90048, mfd->cursor_buf_phys);
+               /* order the writes the cursor_buf before updating the
+                * hardware */
+//             dma_coherent_pre_ops();
+               MDP_OUTP(MDP_BASE + 0x90060,
+                        (transp_en << 3) | (calpha_en << 1) |
+                        (inp32(MDP_BASE + 0x90060) & 0x1));
+#ifdef CONFIG_FB_MSM_MDP40
+               MDP_OUTP(MDP_BASE + 0x90064, (alpha << 24));
+               MDP_OUTP(MDP_BASE + 0x90068, (0xffffff & img->bg_color));
+               MDP_OUTP(MDP_BASE + 0x9006C, (0xffffff & img->bg_color));
+#else
+               MDP_OUTP(MDP_BASE + 0x90064,
+                        (alpha << 24) | (0xffffff & img->bg_color));
+               MDP_OUTP(MDP_BASE + 0x90068, 0);
+#endif
+       }
+
+       if ((cursor->enable) && (!cursor_enabled)) {
+               cursor_enabled = 1;
+               MDP_OUTP(MDP_BASE + 0x90060, inp32(MDP_BASE + 0x90060) | 0x1);
+       } else if ((!cursor->enable) && (cursor_enabled)) {
+               cursor_enabled = 0;
+               MDP_OUTP(MDP_BASE + 0x90060,
+                        inp32(MDP_BASE + 0x90060) & (~0x1));
+       }
+
+       return 0;
+}
diff --git a/drivers/staging/msm/mdp_dma.c b/drivers/staging/msm/mdp_dma.c
new file mode 100644 (file)
index 0000000..639918b
--- /dev/null
@@ -0,0 +1,561 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mddihost.h"
+
+static uint32 mdp_last_dma2_update_width;
+static uint32 mdp_last_dma2_update_height;
+static uint32 mdp_curr_dma2_update_width;
+static uint32 mdp_curr_dma2_update_height;
+
+ktime_t mdp_dma2_last_update_time = { 0 };
+
+int mdp_lcd_rd_cnt_offset_slow = 20;
+int mdp_lcd_rd_cnt_offset_fast = 20;
+int mdp_vsync_usec_wait_line_too_short = 5;
+uint32 mdp_dma2_update_time_in_usec;
+uint32 mdp_total_vdopkts;
+
+extern u32 msm_fb_debug_enabled;
+extern struct workqueue_struct *mdp_dma_wq;
+
+int vsync_start_y_adjust = 4;
+
+static void mdp_dma2_update_lcd(struct msm_fb_data_type *mfd)
+{
+       MDPIBUF *iBuf = &mfd->ibuf;
+       int mddi_dest = FALSE;
+       uint32 outBpp = iBuf->bpp;
+       uint32 dma2_cfg_reg;
+       uint8 *src;
+       uint32 mddi_ld_param;
+       uint16 mddi_vdo_packet_reg;
+       struct msm_fb_panel_data *pdata =
+           (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+       uint32 ystride = mfd->fbi->fix.line_length;
+
+       dma2_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
+           DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
+
+#ifdef CONFIG_FB_MSM_MDP30
+       /*
+        * Software workaround:  On 7x25/7x27, the MDP will not
+        * respond if dma_w is 1 pixel.  Set the update width to
+        * 2 pixels and adjust the x offset if needed.
+        */
+       if (iBuf->dma_w == 1) {
+               iBuf->dma_w = 2;
+               if (iBuf->dma_x == (iBuf->ibuf_width - 2))
+                       iBuf->dma_x--;
+       }
+#endif
+
+       if (mfd->fb_imgType == MDP_BGR_565)
+               dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+       else
+               dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+       if (outBpp == 4)
+               dma2_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
+
+       if (outBpp == 2)
+               dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+
+       mddi_ld_param = 0;
+       mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
+
+       if ((mfd->panel_info.type == MDDI_PANEL) ||
+           (mfd->panel_info.type == EXT_MDDI_PANEL)) {
+               dma2_cfg_reg |= DMA_OUT_SEL_MDDI;
+               mddi_dest = TRUE;
+
+               if (mfd->panel_info.type == MDDI_PANEL) {
+                       mdp_total_vdopkts++;
+                       if (mfd->panel_info.pdest == DISPLAY_1) {
+                               dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
+                               mddi_ld_param = 0;
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+                               mddi_window_adjust(mfd, iBuf->dma_x,
+                                                  iBuf->dma_w - 1, iBuf->dma_y,
+                                                  iBuf->dma_h - 1);
+#endif
+                       } else {
+                               dma2_cfg_reg |=
+                                   DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY;
+                               mddi_ld_param = 1;
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+                               mddi_window_adjust(mfd, iBuf->dma_x,
+                                                  iBuf->dma_w - 1, iBuf->dma_y,
+                                                  iBuf->dma_h - 1);
+#endif
+                       }
+               } else {
+                       dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL;
+                       mddi_ld_param = 2;
+               }
+       } else {
+               if (mfd->panel_info.pdest == DISPLAY_1) {
+                       dma2_cfg_reg |= DMA_AHBM_LCD_SEL_PRIMARY;
+                       outp32(MDP_EBI2_LCD0, mfd->data_port_phys);
+               } else {
+                       dma2_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
+                       outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
+               }
+       }
+
+       dma2_cfg_reg |= DMA_DITHER_EN;
+
+       src = (uint8 *) iBuf->buf;
+       /* starting input address */
+       src += iBuf->dma_x * outBpp + iBuf->dma_y * ystride;
+
+       mdp_curr_dma2_update_width = iBuf->dma_w;
+       mdp_curr_dma2_update_height = iBuf->dma_h;
+
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef CONFIG_FB_MSM_MDP22
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0184,
+                       (iBuf->dma_h << 16 | iBuf->dma_w));
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0188, src);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x018C, ystride);
+#else
+       MDP_OUTP(MDP_BASE + 0x90004, (iBuf->dma_h << 16 | iBuf->dma_w));
+       MDP_OUTP(MDP_BASE + 0x90008, src);
+       MDP_OUTP(MDP_BASE + 0x9000c, ystride);
+#endif
+
+       if (mfd->panel_info.bpp == 18) {
+               dma2_cfg_reg |= DMA_DSTC0G_6BITS |      /* 666 18BPP */
+                   DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+       } else {
+               dma2_cfg_reg |= DMA_DSTC0G_6BITS |      /* 565 16BPP */
+                   DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+       }
+
+       if (mddi_dest) {
+#ifdef CONFIG_FB_MSM_MDP22
+               MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0194,
+                        (iBuf->dma_y << 16) | iBuf->dma_x);
+               MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0, mddi_ld_param);
+               MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4,
+                        (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+#else
+               MDP_OUTP(MDP_BASE + 0x90010, (iBuf->dma_y << 16) | iBuf->dma_x);
+               MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
+               MDP_OUTP(MDP_BASE + 0x00094,
+                        (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+#endif
+       } else {
+               /* setting EBI2 LCDC write window */
+               pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
+                               iBuf->dma_h);
+       }
+
+       /* dma2 config register */
+#ifdef MDP_HW_VSYNC
+       MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+
+       if ((mfd->use_mdp_vsync) &&
+           (mfd->ibuf.vsync_enable) && (mfd->panel_info.lcd.vsync_enable)) {
+               uint32 start_y;
+
+               if (vsync_start_y_adjust <= iBuf->dma_y)
+                       start_y = iBuf->dma_y - vsync_start_y_adjust;
+               else
+                       start_y =
+                           (mfd->total_lcd_lines - 1) - (vsync_start_y_adjust -
+                                                         iBuf->dma_y);
+
+               /*
+                * MDP VSYNC clock must be On by now so, we don't have to
+                * re-enable it
+                */
+               MDP_OUTP(MDP_BASE + 0x210, start_y);
+               MDP_OUTP(MDP_BASE + 0x20c, 1);  /* enable prim vsync */
+       } else {
+               MDP_OUTP(MDP_BASE + 0x20c, 0);  /* disable prim vsync */
+       }
+#else
+#ifdef CONFIG_FB_MSM_MDP22
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0180, dma2_cfg_reg);
+#else
+       MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+#endif
+#endif /* MDP_HW_VSYNC */
+
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+static ktime_t vt = { 0 };
+int mdp_usec_diff_threshold = 100;
+int mdp_expected_usec_wait;
+
+enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht)
+{
+       struct msm_fb_data_type *mfd = NULL;
+
+       mfd = container_of(ht, struct msm_fb_data_type, dma_hrtimer);
+
+       mdp_pipe_kickoff(MDP_DMA2_TERM, mfd);
+
+       if (msm_fb_debug_enabled) {
+               ktime_t t;
+               int usec_diff;
+               int actual_wait;
+
+               t = ktime_get_real();
+
+               actual_wait =
+                   (t.tv.sec - vt.tv.sec) * 1000000 + (t.tv.nsec -
+                                                       vt.tv.nsec) / 1000;
+               usec_diff = actual_wait - mdp_expected_usec_wait;
+
+               if ((mdp_usec_diff_threshold < usec_diff) || (usec_diff < 0))
+                       MSM_FB_DEBUG
+                           ("HRT Diff = %d usec Exp=%d usec  Act=%d usec\n",
+                            usec_diff, mdp_expected_usec_wait, actual_wait);
+       }
+
+       return HRTIMER_NORESTART;
+}
+
+static void mdp_dma_schedule(struct msm_fb_data_type *mfd, uint32 term)
+{
+       /*
+        * dma2 configure VSYNC block
+        * vsync supported on Primary LCD only for now
+        */
+       int32 mdp_lcd_rd_cnt;
+       uint32 usec_wait_time;
+       uint32 start_y;
+
+       /*
+        * ToDo: if we can move HRT timer callback to workqueue, we can
+        * move DMA2 power on under mdp_pipe_kickoff().
+        * This will save a power for hrt time wait.
+        * However if the latency for context switch (hrt irq -> workqueue)
+        * is too big, we will miss the vsync timing.
+        */
+       if (term == MDP_DMA2_TERM)
+               mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+       mdp_dma2_update_time_in_usec =
+           MDP_KTIME2USEC(mdp_dma2_last_update_time);
+
+       if ((!mfd->ibuf.vsync_enable) || (!mfd->panel_info.lcd.vsync_enable)
+           || (mfd->use_mdp_vsync)) {
+               mdp_pipe_kickoff(term, mfd);
+               return;
+       }
+       /* SW vsync logic starts here */
+
+       /* get current rd counter */
+       mdp_lcd_rd_cnt = mdp_get_lcd_line_counter(mfd);
+       if (mdp_dma2_update_time_in_usec != 0) {
+               uint32 num, den;
+
+               /*
+                * roi width boundary calculation to know the size of pixel
+                * width that MDP can send faster or slower than LCD read
+                * pointer
+                */
+
+               num = mdp_last_dma2_update_width * mdp_last_dma2_update_height;
+               den =
+                   (((mfd->panel_info.lcd.refx100 * mfd->total_lcd_lines) /
+                     1000) * (mdp_dma2_update_time_in_usec / 100)) / 1000;
+
+               if (den == 0)
+                       mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
+                           mfd->panel_info.xres + 1;
+               else
+                       mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
+                           (int)(num / den);
+       }
+
+       if (mfd->vsync_width_boundary[mdp_last_dma2_update_width] >
+           mdp_curr_dma2_update_width) {
+               /* MDP wrp is faster than LCD rdp */
+               mdp_lcd_rd_cnt += mdp_lcd_rd_cnt_offset_fast;
+       } else {
+               /* MDP wrp is slower than LCD rdp */
+               mdp_lcd_rd_cnt -= mdp_lcd_rd_cnt_offset_slow;
+       }
+
+       if (mdp_lcd_rd_cnt < 0)
+               mdp_lcd_rd_cnt = mfd->total_lcd_lines + mdp_lcd_rd_cnt;
+       else if (mdp_lcd_rd_cnt > mfd->total_lcd_lines)
+               mdp_lcd_rd_cnt = mdp_lcd_rd_cnt - mfd->total_lcd_lines - 1;
+
+       /* get wrt pointer position */
+       start_y = mfd->ibuf.dma_y;
+
+       /* measure line difference between start_y and rd counter */
+       if (start_y > mdp_lcd_rd_cnt) {
+               /*
+                * *100 for lcd_ref_hzx100 was already multiplied by 100
+                * *1000000 is for usec conversion
+                */
+
+               if ((start_y - mdp_lcd_rd_cnt) <=
+                   mdp_vsync_usec_wait_line_too_short)
+                       usec_wait_time = 0;
+               else
+                       usec_wait_time =
+                           ((start_y -
+                             mdp_lcd_rd_cnt) * 1000000) /
+                           ((mfd->total_lcd_lines *
+                             mfd->panel_info.lcd.refx100) / 100);
+       } else {
+               if ((start_y + (mfd->total_lcd_lines - mdp_lcd_rd_cnt)) <=
+                   mdp_vsync_usec_wait_line_too_short)
+                       usec_wait_time = 0;
+               else
+                       usec_wait_time =
+                           ((start_y +
+                             (mfd->total_lcd_lines -
+                              mdp_lcd_rd_cnt)) * 1000000) /
+                           ((mfd->total_lcd_lines *
+                             mfd->panel_info.lcd.refx100) / 100);
+       }
+
+       mdp_last_dma2_update_width = mdp_curr_dma2_update_width;
+       mdp_last_dma2_update_height = mdp_curr_dma2_update_height;
+
+       if (usec_wait_time == 0) {
+               mdp_pipe_kickoff(term, mfd);
+       } else {
+               ktime_t wait_time;
+
+               wait_time.tv.sec = 0;
+               wait_time.tv.nsec = usec_wait_time * 1000;
+
+               if (msm_fb_debug_enabled) {
+                       vt = ktime_get_real();
+                       mdp_expected_usec_wait = usec_wait_time;
+               }
+               hrtimer_start(&mfd->dma_hrtimer, wait_time, HRTIMER_MODE_REL);
+       }
+}
+
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+void mdp_dma2_update(struct msm_fb_data_type *mfd)
+{
+       MDPIBUF *iBuf;
+       uint32 upper_height;
+
+       if (mfd->panel.type == EXT_MDDI_PANEL) {
+               mdp_dma2_update_sub(mfd);
+               return;
+       }
+
+       iBuf = &mfd->ibuf;
+
+       upper_height =
+           (uint32) mddi_assign_pkt_height((uint16) iBuf->dma_w,
+                                           (uint16) iBuf->dma_h, 18);
+
+       if (upper_height >= iBuf->dma_h) {
+               mdp_dma2_update_sub(mfd);
+       } else {
+               MDPIBUF lower_height;
+
+               /* sending the upper region first */
+               lower_height = iBuf->dma_h - upper_height;
+               iBuf->dma_h = upper_height;
+               mdp_dma2_update_sub(mfd);
+
+               /* sending the lower region second */
+               iBuf->dma_h = lower_height;
+               iBuf->dma_y += lower_height;
+               iBuf->vsync_enable = FALSE;
+               mdp_dma2_update_sub(mfd);
+       }
+}
+
+void mdp_dma2_update_sub(struct msm_fb_data_type *mfd)
+#else
+void mdp_dma2_update(struct msm_fb_data_type *mfd)
+#endif
+{
+       down(&mfd->dma->mutex);
+       if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
+               down(&mfd->sem);
+               mfd->ibuf_flushed = TRUE;
+               mdp_dma2_update_lcd(mfd);
+
+               mdp_enable_irq(MDP_DMA2_TERM);
+               mfd->dma->busy = TRUE;
+               INIT_COMPLETION(mfd->dma->comp);
+
+               /* schedule DMA to start */
+               mdp_dma_schedule(mfd, MDP_DMA2_TERM);
+               up(&mfd->sem);
+
+               /* wait until DMA finishes the current job */
+               wait_for_completion_killable(&mfd->dma->comp);
+               mdp_disable_irq(MDP_DMA2_TERM);
+
+       /* signal if pan function is waiting for the update completion */
+               if (mfd->pan_waiting) {
+                       mfd->pan_waiting = FALSE;
+                       complete(&mfd->pan_comp);
+               }
+       }
+       up(&mfd->dma->mutex);
+}
+
+void mdp_lcd_update_workqueue_handler(struct work_struct *work)
+{
+       struct msm_fb_data_type *mfd = NULL;
+
+       mfd = container_of(work, struct msm_fb_data_type, dma_update_worker);
+       if (mfd)
+               mfd->dma_fnc(mfd);
+}
+
+void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
+                         boolean sync)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       MDPIBUF *iBuf;
+       int bpp = info->var.bits_per_pixel / 8;
+
+       down(&mfd->sem);
+       iBuf = &mfd->ibuf;
+       iBuf->buf = (uint8 *) info->fix.smem_start;
+       iBuf->buf += info->var.xoffset * bpp +
+                       info->var.yoffset * info->fix.line_length;
+
+       iBuf->ibuf_width = info->var.xres_virtual;
+       iBuf->bpp = bpp;
+
+       iBuf->vsync_enable = sync;
+
+       if (dirty) {
+               /*
+                * ToDo: dirty region check inside var.xoffset+xres
+                * <-> var.yoffset+yres
+                */
+               iBuf->dma_x = dirty->xoffset % info->var.xres;
+               iBuf->dma_y = dirty->yoffset % info->var.yres;
+               iBuf->dma_w = dirty->width;
+               iBuf->dma_h = dirty->height;
+       } else {
+               iBuf->dma_x = 0;
+               iBuf->dma_y = 0;
+               iBuf->dma_w = info->var.xres;
+               iBuf->dma_h = info->var.yres;
+       }
+       mfd->ibuf_flushed = FALSE;
+       up(&mfd->sem);
+}
+
+void mdp_set_offset_info(struct fb_info *info, uint32 addr, uint32 sync)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       MDPIBUF *iBuf;
+
+       int bpp = info->var.bits_per_pixel / 8;
+
+       down(&mfd->sem);
+       iBuf = &mfd->ibuf;
+       iBuf->ibuf_width = info->var.xres_virtual;
+       iBuf->bpp = bpp;
+       iBuf->vsync_enable = sync;
+       iBuf->dma_x = 0;
+       iBuf->dma_y = 0;
+       iBuf->dma_w = info->var.xres;
+       iBuf->dma_h = info->var.yres;
+       iBuf->buf = (uint8 *) addr;
+
+       mfd->ibuf_flushed = FALSE;
+       up(&mfd->sem);
+}
+
+void mdp_dma_pan_update(struct fb_info *info)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       MDPIBUF *iBuf;
+
+       iBuf = &mfd->ibuf;
+
+       if (mfd->sw_currently_refreshing) {
+               /* we need to wait for the pending update */
+               mfd->pan_waiting = TRUE;
+               if (!mfd->ibuf_flushed) {
+                       wait_for_completion_killable(&mfd->pan_comp);
+               }
+               /* waiting for this update to complete */
+               mfd->pan_waiting = TRUE;
+               wait_for_completion_killable(&mfd->pan_comp);
+       } else
+               mfd->dma_fnc(mfd);
+}
+
+void mdp_refresh_screen(unsigned long data)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+
+       if ((mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
+               init_timer(&mfd->refresh_timer);
+               mfd->refresh_timer.function = mdp_refresh_screen;
+               mfd->refresh_timer.data = data;
+
+               if (mfd->dma->busy)
+                       /* come back in 1 msec */
+                       mfd->refresh_timer.expires = jiffies + (HZ / 1000);
+               else
+                       mfd->refresh_timer.expires =
+                           jiffies + mfd->refresh_timer_duration;
+
+               add_timer(&mfd->refresh_timer);
+
+               if (!mfd->dma->busy) {
+                       if (!queue_work(mdp_dma_wq, &mfd->dma_update_worker)) {
+                               MSM_FB_DEBUG("mdp_dma: can't queue_work! -> \
+                       MDP/MDDI/LCD clock speed needs to be increased\n");
+                       }
+               }
+       } else {
+               if (!mfd->hw_refresh)
+                       complete(&mfd->refresher_comp);
+       }
+}
diff --git a/drivers/staging/msm/mdp_dma_lcdc.c b/drivers/staging/msm/mdp_dma_lcdc.c
new file mode 100644 (file)
index 0000000..b57fa1a
--- /dev/null
@@ -0,0 +1,379 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define LCDC_BASE      0xC0000
+#define DTV_BASE       0xD0000
+#define DMA_E_BASE      0xB0000
+#else
+#define LCDC_BASE      0xE0000
+#endif
+
+#define DMA_P_BASE      0x90000
+
+extern spinlock_t mdp_spin_lock;
+#ifndef CONFIG_FB_MSM_MDP40
+extern uint32 mdp_intr_mask;
+#endif
+
+int first_pixel_start_x;
+int first_pixel_start_y;
+
+int mdp_lcdc_on(struct platform_device *pdev)
+{
+       int lcdc_width;
+       int lcdc_height;
+       int lcdc_bpp;
+       int lcdc_border_clr;
+       int lcdc_underflow_clr;
+       int lcdc_hsync_skew;
+
+       int hsync_period;
+       int hsync_ctrl;
+       int vsync_period;
+       int display_hctl;
+       int display_v_start;
+       int display_v_end;
+       int active_hctl;
+       int active_h_start;
+       int active_h_end;
+       int active_v_start;
+       int active_v_end;
+       int ctrl_polarity;
+       int h_back_porch;
+       int h_front_porch;
+       int v_back_porch;
+       int v_front_porch;
+       int hsync_pulse_width;
+       int vsync_pulse_width;
+       int hsync_polarity;
+       int vsync_polarity;
+       int data_en_polarity;
+       int hsync_start_x;
+       int hsync_end_x;
+       uint8 *buf;
+       int bpp;
+       uint32 dma2_cfg_reg;
+       struct fb_info *fbi;
+       struct fb_var_screeninfo *var;
+       struct msm_fb_data_type *mfd;
+       uint32 dma_base;
+       uint32 timer_base = LCDC_BASE;
+       uint32 block = MDP_DMA2_BLOCK;
+       int ret;
+
+       mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       fbi = mfd->fbi;
+       var = &fbi->var;
+
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+       bpp = fbi->var.bits_per_pixel / 8;
+       buf = (uint8 *) fbi->fix.smem_start;
+       buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length;
+
+       dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_DITHER_EN | DMA_OUT_SEL_LCDC;
+
+       if (mfd->fb_imgType == MDP_BGR_565)
+               dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+       else
+               dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+       if (bpp == 2)
+               dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+       else if (bpp == 3)
+               dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB888;
+       else
+               dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888;
+
+       switch (mfd->panel_info.bpp) {
+       case 24:
+               dma2_cfg_reg |= DMA_DSTC0G_8BITS |
+                   DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+               break;
+
+       case 18:
+               dma2_cfg_reg |= DMA_DSTC0G_6BITS |
+                   DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+               break;
+
+       case 16:
+               dma2_cfg_reg |= DMA_DSTC0G_6BITS |
+                   DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+               break;
+
+       default:
+               printk(KERN_ERR "mdp lcdc can't support format %d bpp!\n",
+                      mfd->panel_info.bpp);
+               return -ENODEV;
+       }
+
+       /* DMA register config */
+
+       dma_base = DMA_P_BASE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+       if (mfd->panel.type == HDMI_PANEL)
+               dma_base = DMA_E_BASE;
+#endif
+
+       /* starting address */
+       MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
+       /* active window width and height */
+       MDP_OUTP(MDP_BASE + dma_base + 0x4, ((fbi->var.yres) << 16) |
+                                               (fbi->var.xres));
+       /* buffer ystride */
+       MDP_OUTP(MDP_BASE + dma_base + 0xc, fbi->fix.line_length);
+       /* x/y coordinate = always 0 for lcdc */
+       MDP_OUTP(MDP_BASE + dma_base + 0x10, 0);
+       /* dma config */
+       MDP_OUTP(MDP_BASE + dma_base, dma2_cfg_reg);
+
+       /*
+        * LCDC timing setting
+        */
+       h_back_porch = var->left_margin;
+       h_front_porch = var->right_margin;
+       v_back_porch = var->upper_margin;
+       v_front_porch = var->lower_margin;
+       hsync_pulse_width = var->hsync_len;
+       vsync_pulse_width = var->vsync_len;
+       lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
+       lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
+       lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
+
+       lcdc_width = mfd->panel_info.xres;
+       lcdc_height = mfd->panel_info.yres;
+       lcdc_bpp = mfd->panel_info.bpp;
+
+       hsync_period =
+           hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
+       hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
+       hsync_start_x = hsync_pulse_width + h_back_porch;
+       hsync_end_x = hsync_period - h_front_porch - 1;
+       display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+       vsync_period =
+           (vsync_pulse_width + v_back_porch + lcdc_height +
+            v_front_porch) * hsync_period;
+       display_v_start =
+           (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
+       display_v_end =
+           vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
+
+       if (lcdc_width != var->xres) {
+               active_h_start = hsync_start_x + first_pixel_start_x;
+               active_h_end = active_h_start + var->xres - 1;
+               active_hctl =
+                   ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
+       } else {
+               active_hctl = 0;
+       }
+
+       if (lcdc_height != var->yres) {
+               active_v_start =
+                   display_v_start + first_pixel_start_y * hsync_period;
+               active_v_end = active_v_start + (var->yres) * hsync_period - 1;
+               active_v_start |= ACTIVE_START_Y_EN;
+       } else {
+               active_v_start = 0;
+               active_v_end = 0;
+       }
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+       if (mfd->panel.type == HDMI_PANEL) {
+               block = MDP_DMA_E_BLOCK;
+               timer_base = DTV_BASE;
+               hsync_polarity = 0;
+               vsync_polarity = 0;
+       } else {
+               hsync_polarity = 1;
+               vsync_polarity = 1;
+       }
+
+       lcdc_underflow_clr |= 0x80000000;       /* enable recovery */
+#else
+       hsync_polarity = 0;
+       vsync_polarity = 0;
+#endif
+       data_en_polarity = 0;
+
+       ctrl_polarity =
+           (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
+
+       MDP_OUTP(MDP_BASE + timer_base + 0x4, hsync_ctrl);
+       MDP_OUTP(MDP_BASE + timer_base + 0x8, vsync_period);
+       MDP_OUTP(MDP_BASE + timer_base + 0xc, vsync_pulse_width * hsync_period);
+       if (timer_base == LCDC_BASE) {
+               MDP_OUTP(MDP_BASE + timer_base + 0x10, display_hctl);
+               MDP_OUTP(MDP_BASE + timer_base + 0x14, display_v_start);
+               MDP_OUTP(MDP_BASE + timer_base + 0x18, display_v_end);
+               MDP_OUTP(MDP_BASE + timer_base + 0x28, lcdc_border_clr);
+               MDP_OUTP(MDP_BASE + timer_base + 0x2c, lcdc_underflow_clr);
+               MDP_OUTP(MDP_BASE + timer_base + 0x30, lcdc_hsync_skew);
+               MDP_OUTP(MDP_BASE + timer_base + 0x38, ctrl_polarity);
+               MDP_OUTP(MDP_BASE + timer_base + 0x1c, active_hctl);
+               MDP_OUTP(MDP_BASE + timer_base + 0x20, active_v_start);
+               MDP_OUTP(MDP_BASE + timer_base + 0x24, active_v_end);
+       } else {
+               MDP_OUTP(MDP_BASE + timer_base + 0x18, display_hctl);
+               MDP_OUTP(MDP_BASE + timer_base + 0x1c, display_v_start);
+               MDP_OUTP(MDP_BASE + timer_base + 0x20, display_v_end);
+               MDP_OUTP(MDP_BASE + timer_base + 0x40, lcdc_border_clr);
+               MDP_OUTP(MDP_BASE + timer_base + 0x44, lcdc_underflow_clr);
+               MDP_OUTP(MDP_BASE + timer_base + 0x48, lcdc_hsync_skew);
+               MDP_OUTP(MDP_BASE + timer_base + 0x50, ctrl_polarity);
+               MDP_OUTP(MDP_BASE + timer_base + 0x2c, active_hctl);
+               MDP_OUTP(MDP_BASE + timer_base + 0x30, active_v_start);
+               MDP_OUTP(MDP_BASE + timer_base + 0x38, active_v_end);
+       }
+
+       ret = panel_next_on(pdev);
+       if (ret == 0) {
+               /* enable LCDC block */
+               MDP_OUTP(MDP_BASE + timer_base, 1);
+               mdp_pipe_ctrl(block, MDP_BLOCK_POWER_ON, FALSE);
+       }
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+       return ret;
+}
+
+int mdp_lcdc_off(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct msm_fb_data_type *mfd;
+       uint32 timer_base = LCDC_BASE;
+       uint32 block = MDP_DMA2_BLOCK;
+
+       mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+#ifdef CONFIG_FB_MSM_MDP40
+       if (mfd->panel.type == HDMI_PANEL) {
+               block = MDP_DMA_E_BLOCK;
+               timer_base = DTV_BASE;
+       }
+#endif
+
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+       MDP_OUTP(MDP_BASE + timer_base, 0);
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+       mdp_pipe_ctrl(block, MDP_BLOCK_POWER_OFF, FALSE);
+
+       ret = panel_next_off(pdev);
+
+       /* delay to make sure the last frame finishes */
+       mdelay(100);
+
+       return ret;
+}
+
+void mdp_lcdc_update(struct msm_fb_data_type *mfd)
+{
+       struct fb_info *fbi = mfd->fbi;
+       uint8 *buf;
+       int bpp;
+       unsigned long flag;
+       uint32 dma_base;
+       int irq_block = MDP_DMA2_TERM;
+#ifdef CONFIG_FB_MSM_MDP40
+       int intr = INTR_DMA_P_DONE;
+#endif
+
+       if (!mfd->panel_power_on)
+               return;
+
+       /* no need to power on cmd block since it's lcdc mode */
+
+       if (!mfd->ibuf.visible_swapped) {
+               bpp = fbi->var.bits_per_pixel / 8;
+               buf = (uint8 *) fbi->fix.smem_start;
+               buf += fbi->var.xoffset * bpp +
+               fbi->var.yoffset * fbi->fix.line_length;
+       } else {
+               /* we've done something to update the pointer. */
+               bpp =  mfd->ibuf.bpp;
+               buf = mfd->ibuf.buf;
+       }
+
+       dma_base = DMA_P_BASE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+       if (mfd->panel.type == HDMI_PANEL) {
+               intr = INTR_DMA_E_DONE;
+               irq_block = MDP_DMA_E_TERM;
+               dma_base = DMA_E_BASE;
+       }
+#endif
+
+       /* starting address */
+       MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
+
+       /* enable LCDC irq */
+       spin_lock_irqsave(&mdp_spin_lock, flag);
+       mdp_enable_irq(irq_block);
+       INIT_COMPLETION(mfd->dma->comp);
+       mfd->dma->waiting = TRUE;
+#ifdef CONFIG_FB_MSM_MDP40
+       outp32(MDP_INTR_CLEAR, intr);
+       mdp_intr_mask |= intr;
+       outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+#else
+       outp32(MDP_INTR_CLEAR, LCDC_FRAME_START);
+       mdp_intr_mask |= LCDC_FRAME_START;
+       outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+#endif
+       spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+       if (mfd->ibuf.vsync_enable)
+               wait_for_completion_killable(&mfd->dma->comp);
+       mdp_disable_irq(irq_block);
+}
diff --git a/drivers/staging/msm/mdp_dma_s.c b/drivers/staging/msm/mdp_dma_s.c
new file mode 100644 (file)
index 0000000..0c34a10
--- /dev/null
@@ -0,0 +1,139 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd)
+{
+       MDPIBUF *iBuf = &mfd->ibuf;
+       int mddi_dest = FALSE;
+       uint32 outBpp = iBuf->bpp;
+       uint32 dma_s_cfg_reg;
+       uint8 *src;
+       struct msm_fb_panel_data *pdata =
+           (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+       dma_s_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
+           DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
+
+       if (mfd->fb_imgType == MDP_BGR_565)
+               dma_s_cfg_reg |= DMA_PACK_PATTERN_BGR;
+       else
+               dma_s_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+       if (outBpp == 4)
+               dma_s_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
+
+       if (outBpp == 2)
+               dma_s_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+
+       if (mfd->panel_info.pdest != DISPLAY_2) {
+               printk(KERN_ERR "error: non-secondary type through dma_s!\n");
+               return;
+       }
+
+       if (mfd->panel_info.type == MDDI_PANEL) {
+               dma_s_cfg_reg |= DMA_OUT_SEL_MDDI;
+               mddi_dest = TRUE;
+       } else {
+               dma_s_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
+               outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
+       }
+
+       dma_s_cfg_reg |= DMA_DITHER_EN;
+
+       src = (uint8 *) iBuf->buf;
+       /* starting input address */
+       src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * outBpp;
+
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+       /* PIXELSIZE */
+       MDP_OUTP(MDP_BASE + 0xa0004, (iBuf->dma_h << 16 | iBuf->dma_w));
+       MDP_OUTP(MDP_BASE + 0xa0008, src);      /* ibuf address */
+       MDP_OUTP(MDP_BASE + 0xa000c, iBuf->ibuf_width * outBpp);/* ystride */
+
+       if (mfd->panel_info.bpp == 18) {
+               dma_s_cfg_reg |= DMA_DSTC0G_6BITS |     /* 666 18BPP */
+                   DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+       } else {
+               dma_s_cfg_reg |= DMA_DSTC0G_6BITS |     /* 565 16BPP */
+                   DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+       }
+
+       if (mddi_dest) {
+               MDP_OUTP(MDP_BASE + 0xa0010, (iBuf->dma_y << 16) | iBuf->dma_x);
+               MDP_OUTP(MDP_BASE + 0x00090, 1);
+               MDP_OUTP(MDP_BASE + 0x00094,
+                               (MDDI_VDO_PACKET_DESC << 16) |
+                               mfd->panel_info.mddi.vdopkt);
+       } else {
+               /* setting LCDC write window */
+               pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
+                               iBuf->dma_h);
+       }
+
+       MDP_OUTP(MDP_BASE + 0xa0000, dma_s_cfg_reg);
+
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+       mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
+}
+
+void mdp_dma_s_update(struct msm_fb_data_type *mfd)
+{
+       down(&mfd->dma->mutex);
+       if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
+               down(&mfd->sem);
+               mdp_enable_irq(MDP_DMA_S_TERM);
+               mfd->dma->busy = TRUE;
+               INIT_COMPLETION(mfd->dma->comp);
+               mfd->ibuf_flushed = TRUE;
+               mdp_dma_s_update_lcd(mfd);
+               up(&mfd->sem);
+
+               /* wait until DMA finishes the current job */
+               wait_for_completion_killable(&mfd->dma->comp);
+               mdp_disable_irq(MDP_DMA_S_TERM);
+
+       /* signal if pan function is waiting for the update completion */
+               if (mfd->pan_waiting) {
+                       mfd->pan_waiting = FALSE;
+                       complete(&mfd->pan_comp);
+               }
+       }
+       up(&mfd->dma->mutex);
+}
diff --git a/drivers/staging/msm/mdp_dma_tv.c b/drivers/staging/msm/mdp_dma_tv.c
new file mode 100644 (file)
index 0000000..70989fb
--- /dev/null
@@ -0,0 +1,142 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+extern spinlock_t mdp_spin_lock;
+extern uint32 mdp_intr_mask;
+
+int mdp_dma3_on(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+       struct fb_info *fbi;
+       uint8 *buf;
+       int bpp;
+       int ret = 0;
+
+       mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       fbi = mfd->fbi;
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+       bpp = fbi->var.bits_per_pixel / 8;
+       buf = (uint8 *) fbi->fix.smem_start;
+       buf += fbi->var.xoffset * bpp +
+               fbi->var.yoffset * fbi->fix.line_length;
+
+       /* starting address[31..8] of Video frame buffer is CS0 */
+       MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
+
+       mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+       MDP_OUTP(MDP_BASE + 0xC0004, 0x4c60674); /* flicker filter enabled */
+       MDP_OUTP(MDP_BASE + 0xC0010, 0x20);     /* sobel treshold */
+
+       MDP_OUTP(MDP_BASE + 0xC0018, 0xeb0010); /* Y  Max, Y  min */
+       MDP_OUTP(MDP_BASE + 0xC001C, 0xf00010); /* Cb Max, Cb min */
+       MDP_OUTP(MDP_BASE + 0xC0020, 0xf00010); /* Cb Max, Cb min */
+
+       MDP_OUTP(MDP_BASE + 0xC000C, 0x67686970); /* add a few chars for CC */
+       MDP_OUTP(MDP_BASE + 0xC0000, 0x1);      /* MDP tv out enable */
+
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+       ret = panel_next_on(pdev);
+
+       return ret;
+}
+
+int mdp_dma3_off(struct platform_device *pdev)
+{
+       int ret = 0;
+
+       ret = panel_next_off(pdev);
+       if (ret)
+               return ret;
+
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+       MDP_OUTP(MDP_BASE + 0xC0000, 0x0);
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+       mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+       /* delay to make sure the last frame finishes */
+       mdelay(100);
+
+       return ret;
+}
+
+void mdp_dma3_update(struct msm_fb_data_type *mfd)
+{
+       struct fb_info *fbi = mfd->fbi;
+       uint8 *buf;
+       int bpp;
+       unsigned long flag;
+
+       if (!mfd->panel_power_on)
+               return;
+
+       /* no need to power on cmd block since dma3 is running */
+       bpp = fbi->var.bits_per_pixel / 8;
+       buf = (uint8 *) fbi->fix.smem_start;
+       buf += fbi->var.xoffset * bpp +
+               fbi->var.yoffset * fbi->fix.line_length;
+       MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
+
+       spin_lock_irqsave(&mdp_spin_lock, flag);
+       mdp_enable_irq(MDP_DMA3_TERM);
+       INIT_COMPLETION(mfd->dma->comp);
+       mfd->dma->waiting = TRUE;
+
+       outp32(MDP_INTR_CLEAR, TV_OUT_DMA3_START);
+       mdp_intr_mask |= TV_OUT_DMA3_START;
+       outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+       spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+       wait_for_completion_killable(&mfd->dma->comp);
+       mdp_disable_irq(MDP_DMA3_TERM);
+}
diff --git a/drivers/staging/msm/mdp_hw_init.c b/drivers/staging/msm/mdp_hw_init.c
new file mode 100644 (file)
index 0000000..807362a
--- /dev/null
@@ -0,0 +1,720 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "mdp.h"
+
+/* mdp primary csc limit vector */
+uint32 mdp_plv[] = { 0x10, 0xeb, 0x10, 0xf0 };
+
+/* Color Coefficient matrix for YUV -> RGB */
+struct mdp_ccs mdp_ccs_yuv2rgb = {
+       MDP_CCS_YUV2RGB,
+       {
+               0x254,
+               0x000,
+               0x331,
+               0x254,
+               0xff38,
+               0xfe61,
+               0x254,
+               0x409,
+               0x000,
+       },
+       {
+#ifdef CONFIG_FB_MSM_MDP31
+               0x1f0,
+               0x180,
+               0x180
+#else
+               0x10,
+               0x80,
+               0x80
+#endif
+       }
+};
+
+/* Color Coefficient matrix for RGB -> YUV */
+struct mdp_ccs mdp_ccs_rgb2yuv = {
+       MDP_CCS_RGB2YUV,
+       {
+               0x83,
+               0x102,
+               0x32,
+               0xffb5,
+               0xff6c,
+               0xe1,
+               0xe1,
+               0xff45,
+               0xffdc,
+       },
+#ifdef CONFIG_FB_MSM_MDP31
+       {
+               0x10,
+               0x80,
+               0x80
+       }
+#endif
+};
+
+static void mdp_load_lut_param(void)
+{
+       outpdw(MDP_BASE + 0x40800, 0x0);
+       outpdw(MDP_BASE + 0x40804, 0x151515);
+       outpdw(MDP_BASE + 0x40808, 0x1d1d1d);
+       outpdw(MDP_BASE + 0x4080c, 0x232323);
+       outpdw(MDP_BASE + 0x40810, 0x272727);
+       outpdw(MDP_BASE + 0x40814, 0x2b2b2b);
+       outpdw(MDP_BASE + 0x40818, 0x2f2f2f);
+       outpdw(MDP_BASE + 0x4081c, 0x333333);
+       outpdw(MDP_BASE + 0x40820, 0x363636);
+       outpdw(MDP_BASE + 0x40824, 0x393939);
+       outpdw(MDP_BASE + 0x40828, 0x3b3b3b);
+       outpdw(MDP_BASE + 0x4082c, 0x3e3e3e);
+       outpdw(MDP_BASE + 0x40830, 0x404040);
+       outpdw(MDP_BASE + 0x40834, 0x434343);
+       outpdw(MDP_BASE + 0x40838, 0x454545);
+       outpdw(MDP_BASE + 0x4083c, 0x474747);
+       outpdw(MDP_BASE + 0x40840, 0x494949);
+       outpdw(MDP_BASE + 0x40844, 0x4b4b4b);
+       outpdw(MDP_BASE + 0x40848, 0x4d4d4d);
+       outpdw(MDP_BASE + 0x4084c, 0x4f4f4f);
+       outpdw(MDP_BASE + 0x40850, 0x515151);
+       outpdw(MDP_BASE + 0x40854, 0x535353);
+       outpdw(MDP_BASE + 0x40858, 0x555555);
+       outpdw(MDP_BASE + 0x4085c, 0x565656);
+       outpdw(MDP_BASE + 0x40860, 0x585858);
+       outpdw(MDP_BASE + 0x40864, 0x5a5a5a);
+       outpdw(MDP_BASE + 0x40868, 0x5b5b5b);
+       outpdw(MDP_BASE + 0x4086c, 0x5d5d5d);
+       outpdw(MDP_BASE + 0x40870, 0x5e5e5e);
+       outpdw(MDP_BASE + 0x40874, 0x606060);
+       outpdw(MDP_BASE + 0x40878, 0x616161);
+       outpdw(MDP_BASE + 0x4087c, 0x636363);
+       outpdw(MDP_BASE + 0x40880, 0x646464);
+       outpdw(MDP_BASE + 0x40884, 0x666666);
+       outpdw(MDP_BASE + 0x40888, 0x676767);
+       outpdw(MDP_BASE + 0x4088c, 0x686868);
+       outpdw(MDP_BASE + 0x40890, 0x6a6a6a);
+       outpdw(MDP_BASE + 0x40894, 0x6b6b6b);
+       outpdw(MDP_BASE + 0x40898, 0x6c6c6c);
+       outpdw(MDP_BASE + 0x4089c, 0x6e6e6e);
+       outpdw(MDP_BASE + 0x408a0, 0x6f6f6f);
+       outpdw(MDP_BASE + 0x408a4, 0x707070);
+       outpdw(MDP_BASE + 0x408a8, 0x717171);
+       outpdw(MDP_BASE + 0x408ac, 0x727272);
+       outpdw(MDP_BASE + 0x408b0, 0x747474);
+       outpdw(MDP_BASE + 0x408b4, 0x757575);
+       outpdw(MDP_BASE + 0x408b8, 0x767676);
+       outpdw(MDP_BASE + 0x408bc, 0x777777);
+       outpdw(MDP_BASE + 0x408c0, 0x787878);
+       outpdw(MDP_BASE + 0x408c4, 0x797979);
+       outpdw(MDP_BASE + 0x408c8, 0x7a7a7a);
+       outpdw(MDP_BASE + 0x408cc, 0x7c7c7c);
+       outpdw(MDP_BASE + 0x408d0, 0x7d7d7d);
+       outpdw(MDP_BASE + 0x408d4, 0x7e7e7e);
+       outpdw(MDP_BASE + 0x408d8, 0x7f7f7f);
+       outpdw(MDP_BASE + 0x408dc, 0x808080);
+       outpdw(MDP_BASE + 0x408e0, 0x818181);
+       outpdw(MDP_BASE + 0x408e4, 0x828282);
+       outpdw(MDP_BASE + 0x408e8, 0x838383);
+       outpdw(MDP_BASE + 0x408ec, 0x848484);
+       outpdw(MDP_BASE + 0x408f0, 0x858585);
+       outpdw(MDP_BASE + 0x408f4, 0x868686);
+       outpdw(MDP_BASE + 0x408f8, 0x878787);
+       outpdw(MDP_BASE + 0x408fc, 0x888888);
+       outpdw(MDP_BASE + 0x40900, 0x898989);
+       outpdw(MDP_BASE + 0x40904, 0x8a8a8a);
+       outpdw(MDP_BASE + 0x40908, 0x8b8b8b);
+       outpdw(MDP_BASE + 0x4090c, 0x8c8c8c);
+       outpdw(MDP_BASE + 0x40910, 0x8d8d8d);
+       outpdw(MDP_BASE + 0x40914, 0x8e8e8e);
+       outpdw(MDP_BASE + 0x40918, 0x8f8f8f);
+       outpdw(MDP_BASE + 0x4091c, 0x8f8f8f);
+       outpdw(MDP_BASE + 0x40920, 0x909090);
+       outpdw(MDP_BASE + 0x40924, 0x919191);
+       outpdw(MDP_BASE + 0x40928, 0x929292);
+       outpdw(MDP_BASE + 0x4092c, 0x939393);
+       outpdw(MDP_BASE + 0x40930, 0x949494);
+       outpdw(MDP_BASE + 0x40934, 0x959595);
+       outpdw(MDP_BASE + 0x40938, 0x969696);
+       outpdw(MDP_BASE + 0x4093c, 0x969696);
+       outpdw(MDP_BASE + 0x40940, 0x979797);
+       outpdw(MDP_BASE + 0x40944, 0x989898);
+       outpdw(MDP_BASE + 0x40948, 0x999999);
+       outpdw(MDP_BASE + 0x4094c, 0x9a9a9a);
+       outpdw(MDP_BASE + 0x40950, 0x9b9b9b);
+       outpdw(MDP_BASE + 0x40954, 0x9c9c9c);
+       outpdw(MDP_BASE + 0x40958, 0x9c9c9c);
+       outpdw(MDP_BASE + 0x4095c, 0x9d9d9d);
+       outpdw(MDP_BASE + 0x40960, 0x9e9e9e);
+       outpdw(MDP_BASE + 0x40964, 0x9f9f9f);
+       outpdw(MDP_BASE + 0x40968, 0xa0a0a0);
+       outpdw(MDP_BASE + 0x4096c, 0xa0a0a0);
+       outpdw(MDP_BASE + 0x40970, 0xa1a1a1);
+       outpdw(MDP_BASE + 0x40974, 0xa2a2a2);
+       outpdw(MDP_BASE + 0x40978, 0xa3a3a3);
+       outpdw(MDP_BASE + 0x4097c, 0xa4a4a4);
+       outpdw(MDP_BASE + 0x40980, 0xa4a4a4);
+       outpdw(MDP_BASE + 0x40984, 0xa5a5a5);
+       outpdw(MDP_BASE + 0x40988, 0xa6a6a6);
+       outpdw(MDP_BASE + 0x4098c, 0xa7a7a7);
+       outpdw(MDP_BASE + 0x40990, 0xa7a7a7);
+       outpdw(MDP_BASE + 0x40994, 0xa8a8a8);
+       outpdw(MDP_BASE + 0x40998, 0xa9a9a9);
+       outpdw(MDP_BASE + 0x4099c, 0xaaaaaa);
+       outpdw(MDP_BASE + 0x409a0, 0xaaaaaa);
+       outpdw(MDP_BASE + 0x409a4, 0xababab);
+       outpdw(MDP_BASE + 0x409a8, 0xacacac);
+       outpdw(MDP_BASE + 0x409ac, 0xadadad);
+       outpdw(MDP_BASE + 0x409b0, 0xadadad);
+       outpdw(MDP_BASE + 0x409b4, 0xaeaeae);
+       outpdw(MDP_BASE + 0x409b8, 0xafafaf);
+       outpdw(MDP_BASE + 0x409bc, 0xafafaf);
+       outpdw(MDP_BASE + 0x409c0, 0xb0b0b0);
+       outpdw(MDP_BASE + 0x409c4, 0xb1b1b1);
+       outpdw(MDP_BASE + 0x409c8, 0xb2b2b2);
+       outpdw(MDP_BASE + 0x409cc, 0xb2b2b2);
+       outpdw(MDP_BASE + 0x409d0, 0xb3b3b3);
+       outpdw(MDP_BASE + 0x409d4, 0xb4b4b4);
+       outpdw(MDP_BASE + 0x409d8, 0xb4b4b4);
+       outpdw(MDP_BASE + 0x409dc, 0xb5b5b5);
+       outpdw(MDP_BASE + 0x409e0, 0xb6b6b6);
+       outpdw(MDP_BASE + 0x409e4, 0xb6b6b6);
+       outpdw(MDP_BASE + 0x409e8, 0xb7b7b7);
+       outpdw(MDP_BASE + 0x409ec, 0xb8b8b8);
+       outpdw(MDP_BASE + 0x409f0, 0xb8b8b8);
+       outpdw(MDP_BASE + 0x409f4, 0xb9b9b9);
+       outpdw(MDP_BASE + 0x409f8, 0xbababa);
+       outpdw(MDP_BASE + 0x409fc, 0xbababa);
+       outpdw(MDP_BASE + 0x40a00, 0xbbbbbb);
+       outpdw(MDP_BASE + 0x40a04, 0xbcbcbc);
+       outpdw(MDP_BASE + 0x40a08, 0xbcbcbc);
+       outpdw(MDP_BASE + 0x40a0c, 0xbdbdbd);
+       outpdw(MDP_BASE + 0x40a10, 0xbebebe);
+       outpdw(MDP_BASE + 0x40a14, 0xbebebe);
+       outpdw(MDP_BASE + 0x40a18, 0xbfbfbf);
+       outpdw(MDP_BASE + 0x40a1c, 0xc0c0c0);
+       outpdw(MDP_BASE + 0x40a20, 0xc0c0c0);
+       outpdw(MDP_BASE + 0x40a24, 0xc1c1c1);
+       outpdw(MDP_BASE + 0x40a28, 0xc1c1c1);
+       outpdw(MDP_BASE + 0x40a2c, 0xc2c2c2);
+       outpdw(MDP_BASE + 0x40a30, 0xc3c3c3);
+       outpdw(MDP_BASE + 0x40a34, 0xc3c3c3);
+       outpdw(MDP_BASE + 0x40a38, 0xc4c4c4);
+       outpdw(MDP_BASE + 0x40a3c, 0xc5c5c5);
+       outpdw(MDP_BASE + 0x40a40, 0xc5c5c5);
+       outpdw(MDP_BASE + 0x40a44, 0xc6c6c6);
+       outpdw(MDP_BASE + 0x40a48, 0xc6c6c6);
+       outpdw(MDP_BASE + 0x40a4c, 0xc7c7c7);
+       outpdw(MDP_BASE + 0x40a50, 0xc8c8c8);
+       outpdw(MDP_BASE + 0x40a54, 0xc8c8c8);
+       outpdw(MDP_BASE + 0x40a58, 0xc9c9c9);
+       outpdw(MDP_BASE + 0x40a5c, 0xc9c9c9);
+       outpdw(MDP_BASE + 0x40a60, 0xcacaca);
+       outpdw(MDP_BASE + 0x40a64, 0xcbcbcb);
+       outpdw(MDP_BASE + 0x40a68, 0xcbcbcb);
+       outpdw(MDP_BASE + 0x40a6c, 0xcccccc);
+       outpdw(MDP_BASE + 0x40a70, 0xcccccc);
+       outpdw(MDP_BASE + 0x40a74, 0xcdcdcd);
+       outpdw(MDP_BASE + 0x40a78, 0xcecece);
+       outpdw(MDP_BASE + 0x40a7c, 0xcecece);
+       outpdw(MDP_BASE + 0x40a80, 0xcfcfcf);
+       outpdw(MDP_BASE + 0x40a84, 0xcfcfcf);
+       outpdw(MDP_BASE + 0x40a88, 0xd0d0d0);
+       outpdw(MDP_BASE + 0x40a8c, 0xd0d0d0);
+       outpdw(MDP_BASE + 0x40a90, 0xd1d1d1);
+       outpdw(MDP_BASE + 0x40a94, 0xd2d2d2);
+       outpdw(MDP_BASE + 0x40a98, 0xd2d2d2);
+       outpdw(MDP_BASE + 0x40a9c, 0xd3d3d3);
+       outpdw(MDP_BASE + 0x40aa0, 0xd3d3d3);
+       outpdw(MDP_BASE + 0x40aa4, 0xd4d4d4);
+       outpdw(MDP_BASE + 0x40aa8, 0xd4d4d4);
+       outpdw(MDP_BASE + 0x40aac, 0xd5d5d5);
+       outpdw(MDP_BASE + 0x40ab0, 0xd6d6d6);
+       outpdw(MDP_BASE + 0x40ab4, 0xd6d6d6);
+       outpdw(MDP_BASE + 0x40ab8, 0xd7d7d7);
+       outpdw(MDP_BASE + 0x40abc, 0xd7d7d7);
+       outpdw(MDP_BASE + 0x40ac0, 0xd8d8d8);
+       outpdw(MDP_BASE + 0x40ac4, 0xd8d8d8);
+       outpdw(MDP_BASE + 0x40ac8, 0xd9d9d9);
+       outpdw(MDP_BASE + 0x40acc, 0xd9d9d9);
+       outpdw(MDP_BASE + 0x40ad0, 0xdadada);
+       outpdw(MDP_BASE + 0x40ad4, 0xdbdbdb);
+       outpdw(MDP_BASE + 0x40ad8, 0xdbdbdb);
+       outpdw(MDP_BASE + 0x40adc, 0xdcdcdc);
+       outpdw(MDP_BASE + 0x40ae0, 0xdcdcdc);
+       outpdw(MDP_BASE + 0x40ae4, 0xdddddd);
+       outpdw(MDP_BASE + 0x40ae8, 0xdddddd);
+       outpdw(MDP_BASE + 0x40aec, 0xdedede);
+       outpdw(MDP_BASE + 0x40af0, 0xdedede);
+       outpdw(MDP_BASE + 0x40af4, 0xdfdfdf);
+       outpdw(MDP_BASE + 0x40af8, 0xdfdfdf);
+       outpdw(MDP_BASE + 0x40afc, 0xe0e0e0);
+       outpdw(MDP_BASE + 0x40b00, 0xe0e0e0);
+       outpdw(MDP_BASE + 0x40b04, 0xe1e1e1);
+       outpdw(MDP_BASE + 0x40b08, 0xe1e1e1);
+       outpdw(MDP_BASE + 0x40b0c, 0xe2e2e2);
+       outpdw(MDP_BASE + 0x40b10, 0xe3e3e3);
+       outpdw(MDP_BASE + 0x40b14, 0xe3e3e3);
+       outpdw(MDP_BASE + 0x40b18, 0xe4e4e4);
+       outpdw(MDP_BASE + 0x40b1c, 0xe4e4e4);
+       outpdw(MDP_BASE + 0x40b20, 0xe5e5e5);
+       outpdw(MDP_BASE + 0x40b24, 0xe5e5e5);
+       outpdw(MDP_BASE + 0x40b28, 0xe6e6e6);
+       outpdw(MDP_BASE + 0x40b2c, 0xe6e6e6);
+       outpdw(MDP_BASE + 0x40b30, 0xe7e7e7);
+       outpdw(MDP_BASE + 0x40b34, 0xe7e7e7);
+       outpdw(MDP_BASE + 0x40b38, 0xe8e8e8);
+       outpdw(MDP_BASE + 0x40b3c, 0xe8e8e8);
+       outpdw(MDP_BASE + 0x40b40, 0xe9e9e9);
+       outpdw(MDP_BASE + 0x40b44, 0xe9e9e9);
+       outpdw(MDP_BASE + 0x40b48, 0xeaeaea);
+       outpdw(MDP_BASE + 0x40b4c, 0xeaeaea);
+       outpdw(MDP_BASE + 0x40b50, 0xebebeb);
+       outpdw(MDP_BASE + 0x40b54, 0xebebeb);
+       outpdw(MDP_BASE + 0x40b58, 0xececec);
+       outpdw(MDP_BASE + 0x40b5c, 0xececec);
+       outpdw(MDP_BASE + 0x40b60, 0xededed);
+       outpdw(MDP_BASE + 0x40b64, 0xededed);
+       outpdw(MDP_BASE + 0x40b68, 0xeeeeee);
+       outpdw(MDP_BASE + 0x40b6c, 0xeeeeee);
+       outpdw(MDP_BASE + 0x40b70, 0xefefef);
+       outpdw(MDP_BASE + 0x40b74, 0xefefef);
+       outpdw(MDP_BASE + 0x40b78, 0xf0f0f0);
+       outpdw(MDP_BASE + 0x40b7c, 0xf0f0f0);
+       outpdw(MDP_BASE + 0x40b80, 0xf1f1f1);
+       outpdw(MDP_BASE + 0x40b84, 0xf1f1f1);
+       outpdw(MDP_BASE + 0x40b88, 0xf2f2f2);
+       outpdw(MDP_BASE + 0x40b8c, 0xf2f2f2);
+       outpdw(MDP_BASE + 0x40b90, 0xf2f2f2);
+       outpdw(MDP_BASE + 0x40b94, 0xf3f3f3);
+       outpdw(MDP_BASE + 0x40b98, 0xf3f3f3);
+       outpdw(MDP_BASE + 0x40b9c, 0xf4f4f4);
+       outpdw(MDP_BASE + 0x40ba0, 0xf4f4f4);
+       outpdw(MDP_BASE + 0x40ba4, 0xf5f5f5);
+       outpdw(MDP_BASE + 0x40ba8, 0xf5f5f5);
+       outpdw(MDP_BASE + 0x40bac, 0xf6f6f6);
+       outpdw(MDP_BASE + 0x40bb0, 0xf6f6f6);
+       outpdw(MDP_BASE + 0x40bb4, 0xf7f7f7);
+       outpdw(MDP_BASE + 0x40bb8, 0xf7f7f7);
+       outpdw(MDP_BASE + 0x40bbc, 0xf8f8f8);
+       outpdw(MDP_BASE + 0x40bc0, 0xf8f8f8);
+       outpdw(MDP_BASE + 0x40bc4, 0xf9f9f9);
+       outpdw(MDP_BASE + 0x40bc8, 0xf9f9f9);
+       outpdw(MDP_BASE + 0x40bcc, 0xfafafa);
+       outpdw(MDP_BASE + 0x40bd0, 0xfafafa);
+       outpdw(MDP_BASE + 0x40bd4, 0xfafafa);
+       outpdw(MDP_BASE + 0x40bd8, 0xfbfbfb);
+       outpdw(MDP_BASE + 0x40bdc, 0xfbfbfb);
+       outpdw(MDP_BASE + 0x40be0, 0xfcfcfc);
+       outpdw(MDP_BASE + 0x40be4, 0xfcfcfc);
+       outpdw(MDP_BASE + 0x40be8, 0xfdfdfd);
+       outpdw(MDP_BASE + 0x40bec, 0xfdfdfd);
+       outpdw(MDP_BASE + 0x40bf0, 0xfefefe);
+       outpdw(MDP_BASE + 0x40bf4, 0xfefefe);
+       outpdw(MDP_BASE + 0x40bf8, 0xffffff);
+       outpdw(MDP_BASE + 0x40bfc, 0xffffff);
+       outpdw(MDP_BASE + 0x40c00, 0x0);
+       outpdw(MDP_BASE + 0x40c04, 0x0);
+       outpdw(MDP_BASE + 0x40c08, 0x0);
+       outpdw(MDP_BASE + 0x40c0c, 0x0);
+       outpdw(MDP_BASE + 0x40c10, 0x0);
+       outpdw(MDP_BASE + 0x40c14, 0x0);
+       outpdw(MDP_BASE + 0x40c18, 0x0);
+       outpdw(MDP_BASE + 0x40c1c, 0x0);
+       outpdw(MDP_BASE + 0x40c20, 0x0);
+       outpdw(MDP_BASE + 0x40c24, 0x0);
+       outpdw(MDP_BASE + 0x40c28, 0x0);
+       outpdw(MDP_BASE + 0x40c2c, 0x0);
+       outpdw(MDP_BASE + 0x40c30, 0x0);
+       outpdw(MDP_BASE + 0x40c34, 0x0);
+       outpdw(MDP_BASE + 0x40c38, 0x0);
+       outpdw(MDP_BASE + 0x40c3c, 0x0);
+       outpdw(MDP_BASE + 0x40c40, 0x10101);
+       outpdw(MDP_BASE + 0x40c44, 0x10101);
+       outpdw(MDP_BASE + 0x40c48, 0x10101);
+       outpdw(MDP_BASE + 0x40c4c, 0x10101);
+       outpdw(MDP_BASE + 0x40c50, 0x10101);
+       outpdw(MDP_BASE + 0x40c54, 0x10101);
+       outpdw(MDP_BASE + 0x40c58, 0x10101);
+       outpdw(MDP_BASE + 0x40c5c, 0x10101);
+       outpdw(MDP_BASE + 0x40c60, 0x10101);
+       outpdw(MDP_BASE + 0x40c64, 0x10101);
+       outpdw(MDP_BASE + 0x40c68, 0x20202);
+       outpdw(MDP_BASE + 0x40c6c, 0x20202);
+       outpdw(MDP_BASE + 0x40c70, 0x20202);
+       outpdw(MDP_BASE + 0x40c74, 0x20202);
+       outpdw(MDP_BASE + 0x40c78, 0x20202);
+       outpdw(MDP_BASE + 0x40c7c, 0x20202);
+       outpdw(MDP_BASE + 0x40c80, 0x30303);
+       outpdw(MDP_BASE + 0x40c84, 0x30303);
+       outpdw(MDP_BASE + 0x40c88, 0x30303);
+       outpdw(MDP_BASE + 0x40c8c, 0x30303);
+       outpdw(MDP_BASE + 0x40c90, 0x30303);
+       outpdw(MDP_BASE + 0x40c94, 0x40404);
+       outpdw(MDP_BASE + 0x40c98, 0x40404);
+       outpdw(MDP_BASE + 0x40c9c, 0x40404);
+       outpdw(MDP_BASE + 0x40ca0, 0x40404);
+       outpdw(MDP_BASE + 0x40ca4, 0x40404);
+       outpdw(MDP_BASE + 0x40ca8, 0x50505);
+       outpdw(MDP_BASE + 0x40cac, 0x50505);
+       outpdw(MDP_BASE + 0x40cb0, 0x50505);
+       outpdw(MDP_BASE + 0x40cb4, 0x50505);
+       outpdw(MDP_BASE + 0x40cb8, 0x60606);
+       outpdw(MDP_BASE + 0x40cbc, 0x60606);
+       outpdw(MDP_BASE + 0x40cc0, 0x60606);
+       outpdw(MDP_BASE + 0x40cc4, 0x70707);
+       outpdw(MDP_BASE + 0x40cc8, 0x70707);
+       outpdw(MDP_BASE + 0x40ccc, 0x70707);
+       outpdw(MDP_BASE + 0x40cd0, 0x70707);
+       outpdw(MDP_BASE + 0x40cd4, 0x80808);
+       outpdw(MDP_BASE + 0x40cd8, 0x80808);
+       outpdw(MDP_BASE + 0x40cdc, 0x80808);
+       outpdw(MDP_BASE + 0x40ce0, 0x90909);
+       outpdw(MDP_BASE + 0x40ce4, 0x90909);
+       outpdw(MDP_BASE + 0x40ce8, 0xa0a0a);
+       outpdw(MDP_BASE + 0x40cec, 0xa0a0a);
+       outpdw(MDP_BASE + 0x40cf0, 0xa0a0a);
+       outpdw(MDP_BASE + 0x40cf4, 0xb0b0b);
+       outpdw(MDP_BASE + 0x40cf8, 0xb0b0b);
+       outpdw(MDP_BASE + 0x40cfc, 0xb0b0b);
+       outpdw(MDP_BASE + 0x40d00, 0xc0c0c);
+       outpdw(MDP_BASE + 0x40d04, 0xc0c0c);
+       outpdw(MDP_BASE + 0x40d08, 0xd0d0d);
+       outpdw(MDP_BASE + 0x40d0c, 0xd0d0d);
+       outpdw(MDP_BASE + 0x40d10, 0xe0e0e);
+       outpdw(MDP_BASE + 0x40d14, 0xe0e0e);
+       outpdw(MDP_BASE + 0x40d18, 0xe0e0e);
+       outpdw(MDP_BASE + 0x40d1c, 0xf0f0f);
+       outpdw(MDP_BASE + 0x40d20, 0xf0f0f);
+       outpdw(MDP_BASE + 0x40d24, 0x101010);
+       outpdw(MDP_BASE + 0x40d28, 0x101010);
+       outpdw(MDP_BASE + 0x40d2c, 0x111111);
+       outpdw(MDP_BASE + 0x40d30, 0x111111);
+       outpdw(MDP_BASE + 0x40d34, 0x121212);
+       outpdw(MDP_BASE + 0x40d38, 0x121212);
+       outpdw(MDP_BASE + 0x40d3c, 0x131313);
+       outpdw(MDP_BASE + 0x40d40, 0x131313);
+       outpdw(MDP_BASE + 0x40d44, 0x141414);
+       outpdw(MDP_BASE + 0x40d48, 0x151515);
+       outpdw(MDP_BASE + 0x40d4c, 0x151515);
+       outpdw(MDP_BASE + 0x40d50, 0x161616);
+       outpdw(MDP_BASE + 0x40d54, 0x161616);
+       outpdw(MDP_BASE + 0x40d58, 0x171717);
+       outpdw(MDP_BASE + 0x40d5c, 0x171717);
+       outpdw(MDP_BASE + 0x40d60, 0x181818);
+       outpdw(MDP_BASE + 0x40d64, 0x191919);
+       outpdw(MDP_BASE + 0x40d68, 0x191919);
+       outpdw(MDP_BASE + 0x40d6c, 0x1a1a1a);
+       outpdw(MDP_BASE + 0x40d70, 0x1b1b1b);
+       outpdw(MDP_BASE + 0x40d74, 0x1b1b1b);
+       outpdw(MDP_BASE + 0x40d78, 0x1c1c1c);
+       outpdw(MDP_BASE + 0x40d7c, 0x1c1c1c);
+       outpdw(MDP_BASE + 0x40d80, 0x1d1d1d);
+       outpdw(MDP_BASE + 0x40d84, 0x1e1e1e);
+       outpdw(MDP_BASE + 0x40d88, 0x1f1f1f);
+       outpdw(MDP_BASE + 0x40d8c, 0x1f1f1f);
+       outpdw(MDP_BASE + 0x40d90, 0x202020);
+       outpdw(MDP_BASE + 0x40d94, 0x212121);
+       outpdw(MDP_BASE + 0x40d98, 0x212121);
+       outpdw(MDP_BASE + 0x40d9c, 0x222222);
+       outpdw(MDP_BASE + 0x40da0, 0x232323);
+       outpdw(MDP_BASE + 0x40da4, 0x242424);
+       outpdw(MDP_BASE + 0x40da8, 0x242424);
+       outpdw(MDP_BASE + 0x40dac, 0x252525);
+       outpdw(MDP_BASE + 0x40db0, 0x262626);
+       outpdw(MDP_BASE + 0x40db4, 0x272727);
+       outpdw(MDP_BASE + 0x40db8, 0x272727);
+       outpdw(MDP_BASE + 0x40dbc, 0x282828);
+       outpdw(MDP_BASE + 0x40dc0, 0x292929);
+       outpdw(MDP_BASE + 0x40dc4, 0x2a2a2a);
+       outpdw(MDP_BASE + 0x40dc8, 0x2b2b2b);
+       outpdw(MDP_BASE + 0x40dcc, 0x2c2c2c);
+       outpdw(MDP_BASE + 0x40dd0, 0x2c2c2c);
+       outpdw(MDP_BASE + 0x40dd4, 0x2d2d2d);
+       outpdw(MDP_BASE + 0x40dd8, 0x2e2e2e);
+       outpdw(MDP_BASE + 0x40ddc, 0x2f2f2f);
+       outpdw(MDP_BASE + 0x40de0, 0x303030);
+       outpdw(MDP_BASE + 0x40de4, 0x313131);
+       outpdw(MDP_BASE + 0x40de8, 0x323232);
+       outpdw(MDP_BASE + 0x40dec, 0x333333);
+       outpdw(MDP_BASE + 0x40df0, 0x333333);
+       outpdw(MDP_BASE + 0x40df4, 0x343434);
+       outpdw(MDP_BASE + 0x40df8, 0x353535);
+       outpdw(MDP_BASE + 0x40dfc, 0x363636);
+       outpdw(MDP_BASE + 0x40e00, 0x373737);
+       outpdw(MDP_BASE + 0x40e04, 0x383838);
+       outpdw(MDP_BASE + 0x40e08, 0x393939);
+       outpdw(MDP_BASE + 0x40e0c, 0x3a3a3a);
+       outpdw(MDP_BASE + 0x40e10, 0x3b3b3b);
+       outpdw(MDP_BASE + 0x40e14, 0x3c3c3c);
+       outpdw(MDP_BASE + 0x40e18, 0x3d3d3d);
+       outpdw(MDP_BASE + 0x40e1c, 0x3e3e3e);
+       outpdw(MDP_BASE + 0x40e20, 0x3f3f3f);
+       outpdw(MDP_BASE + 0x40e24, 0x404040);
+       outpdw(MDP_BASE + 0x40e28, 0x414141);
+       outpdw(MDP_BASE + 0x40e2c, 0x424242);
+       outpdw(MDP_BASE + 0x40e30, 0x434343);
+       outpdw(MDP_BASE + 0x40e34, 0x444444);
+       outpdw(MDP_BASE + 0x40e38, 0x464646);
+       outpdw(MDP_BASE + 0x40e3c, 0x474747);
+       outpdw(MDP_BASE + 0x40e40, 0x484848);
+       outpdw(MDP_BASE + 0x40e44, 0x494949);
+       outpdw(MDP_BASE + 0x40e48, 0x4a4a4a);
+       outpdw(MDP_BASE + 0x40e4c, 0x4b4b4b);
+       outpdw(MDP_BASE + 0x40e50, 0x4c4c4c);
+       outpdw(MDP_BASE + 0x40e54, 0x4d4d4d);
+       outpdw(MDP_BASE + 0x40e58, 0x4f4f4f);
+       outpdw(MDP_BASE + 0x40e5c, 0x505050);
+       outpdw(MDP_BASE + 0x40e60, 0x515151);
+       outpdw(MDP_BASE + 0x40e64, 0x525252);
+       outpdw(MDP_BASE + 0x40e68, 0x535353);
+       outpdw(MDP_BASE + 0x40e6c, 0x545454);
+       outpdw(MDP_BASE + 0x40e70, 0x565656);
+       outpdw(MDP_BASE + 0x40e74, 0x575757);
+       outpdw(MDP_BASE + 0x40e78, 0x585858);
+       outpdw(MDP_BASE + 0x40e7c, 0x595959);
+       outpdw(MDP_BASE + 0x40e80, 0x5b5b5b);
+       outpdw(MDP_BASE + 0x40e84, 0x5c5c5c);
+       outpdw(MDP_BASE + 0x40e88, 0x5d5d5d);
+       outpdw(MDP_BASE + 0x40e8c, 0x5e5e5e);
+       outpdw(MDP_BASE + 0x40e90, 0x606060);
+       outpdw(MDP_BASE + 0x40e94, 0x616161);
+       outpdw(MDP_BASE + 0x40e98, 0x626262);
+       outpdw(MDP_BASE + 0x40e9c, 0x646464);
+       outpdw(MDP_BASE + 0x40ea0, 0x656565);
+       outpdw(MDP_BASE + 0x40ea4, 0x666666);
+       outpdw(MDP_BASE + 0x40ea8, 0x686868);
+       outpdw(MDP_BASE + 0x40eac, 0x696969);
+       outpdw(MDP_BASE + 0x40eb0, 0x6a6a6a);
+       outpdw(MDP_BASE + 0x40eb4, 0x6c6c6c);
+       outpdw(MDP_BASE + 0x40eb8, 0x6d6d6d);
+       outpdw(MDP_BASE + 0x40ebc, 0x6f6f6f);
+       outpdw(MDP_BASE + 0x40ec0, 0x707070);
+       outpdw(MDP_BASE + 0x40ec4, 0x717171);
+       outpdw(MDP_BASE + 0x40ec8, 0x737373);
+       outpdw(MDP_BASE + 0x40ecc, 0x747474);
+       outpdw(MDP_BASE + 0x40ed0, 0x767676);
+       outpdw(MDP_BASE + 0x40ed4, 0x777777);
+       outpdw(MDP_BASE + 0x40ed8, 0x797979);
+       outpdw(MDP_BASE + 0x40edc, 0x7a7a7a);
+       outpdw(MDP_BASE + 0x40ee0, 0x7c7c7c);
+       outpdw(MDP_BASE + 0x40ee4, 0x7d7d7d);
+       outpdw(MDP_BASE + 0x40ee8, 0x7f7f7f);
+       outpdw(MDP_BASE + 0x40eec, 0x808080);
+       outpdw(MDP_BASE + 0x40ef0, 0x828282);
+       outpdw(MDP_BASE + 0x40ef4, 0x838383);
+       outpdw(MDP_BASE + 0x40ef8, 0x858585);
+       outpdw(MDP_BASE + 0x40efc, 0x868686);
+       outpdw(MDP_BASE + 0x40f00, 0x888888);
+       outpdw(MDP_BASE + 0x40f04, 0x898989);
+       outpdw(MDP_BASE + 0x40f08, 0x8b8b8b);
+       outpdw(MDP_BASE + 0x40f0c, 0x8d8d8d);
+       outpdw(MDP_BASE + 0x40f10, 0x8e8e8e);
+       outpdw(MDP_BASE + 0x40f14, 0x909090);
+       outpdw(MDP_BASE + 0x40f18, 0x919191);
+       outpdw(MDP_BASE + 0x40f1c, 0x939393);
+       outpdw(MDP_BASE + 0x40f20, 0x959595);
+       outpdw(MDP_BASE + 0x40f24, 0x969696);
+       outpdw(MDP_BASE + 0x40f28, 0x989898);
+       outpdw(MDP_BASE + 0x40f2c, 0x9a9a9a);
+       outpdw(MDP_BASE + 0x40f30, 0x9b9b9b);
+       outpdw(MDP_BASE + 0x40f34, 0x9d9d9d);
+       outpdw(MDP_BASE + 0x40f38, 0x9f9f9f);
+       outpdw(MDP_BASE + 0x40f3c, 0xa1a1a1);
+       outpdw(MDP_BASE + 0x40f40, 0xa2a2a2);
+       outpdw(MDP_BASE + 0x40f44, 0xa4a4a4);
+       outpdw(MDP_BASE + 0x40f48, 0xa6a6a6);
+       outpdw(MDP_BASE + 0x40f4c, 0xa7a7a7);
+       outpdw(MDP_BASE + 0x40f50, 0xa9a9a9);
+       outpdw(MDP_BASE + 0x40f54, 0xababab);
+       outpdw(MDP_BASE + 0x40f58, 0xadadad);
+       outpdw(MDP_BASE + 0x40f5c, 0xafafaf);
+       outpdw(MDP_BASE + 0x40f60, 0xb0b0b0);
+       outpdw(MDP_BASE + 0x40f64, 0xb2b2b2);
+       outpdw(MDP_BASE + 0x40f68, 0xb4b4b4);
+       outpdw(MDP_BASE + 0x40f6c, 0xb6b6b6);
+       outpdw(MDP_BASE + 0x40f70, 0xb8b8b8);
+       outpdw(MDP_BASE + 0x40f74, 0xbababa);
+       outpdw(MDP_BASE + 0x40f78, 0xbbbbbb);
+       outpdw(MDP_BASE + 0x40f7c, 0xbdbdbd);
+       outpdw(MDP_BASE + 0x40f80, 0xbfbfbf);
+       outpdw(MDP_BASE + 0x40f84, 0xc1c1c1);
+       outpdw(MDP_BASE + 0x40f88, 0xc3c3c3);
+       outpdw(MDP_BASE + 0x40f8c, 0xc5c5c5);
+       outpdw(MDP_BASE + 0x40f90, 0xc7c7c7);
+       outpdw(MDP_BASE + 0x40f94, 0xc9c9c9);
+       outpdw(MDP_BASE + 0x40f98, 0xcbcbcb);
+       outpdw(MDP_BASE + 0x40f9c, 0xcdcdcd);
+       outpdw(MDP_BASE + 0x40fa0, 0xcfcfcf);
+       outpdw(MDP_BASE + 0x40fa4, 0xd1d1d1);
+       outpdw(MDP_BASE + 0x40fa8, 0xd3d3d3);
+       outpdw(MDP_BASE + 0x40fac, 0xd5d5d5);
+       outpdw(MDP_BASE + 0x40fb0, 0xd7d7d7);
+       outpdw(MDP_BASE + 0x40fb4, 0xd9d9d9);
+       outpdw(MDP_BASE + 0x40fb8, 0xdbdbdb);
+       outpdw(MDP_BASE + 0x40fbc, 0xdddddd);
+       outpdw(MDP_BASE + 0x40fc0, 0xdfdfdf);
+       outpdw(MDP_BASE + 0x40fc4, 0xe1e1e1);
+       outpdw(MDP_BASE + 0x40fc8, 0xe3e3e3);
+       outpdw(MDP_BASE + 0x40fcc, 0xe5e5e5);
+       outpdw(MDP_BASE + 0x40fd0, 0xe7e7e7);
+       outpdw(MDP_BASE + 0x40fd4, 0xe9e9e9);
+       outpdw(MDP_BASE + 0x40fd8, 0xebebeb);
+       outpdw(MDP_BASE + 0x40fdc, 0xeeeeee);
+       outpdw(MDP_BASE + 0x40fe0, 0xf0f0f0);
+       outpdw(MDP_BASE + 0x40fe4, 0xf2f2f2);
+       outpdw(MDP_BASE + 0x40fe8, 0xf4f4f4);
+       outpdw(MDP_BASE + 0x40fec, 0xf6f6f6);
+       outpdw(MDP_BASE + 0x40ff0, 0xf8f8f8);
+       outpdw(MDP_BASE + 0x40ff4, 0xfbfbfb);
+       outpdw(MDP_BASE + 0x40ff8, 0xfdfdfd);
+       outpdw(MDP_BASE + 0x40ffc, 0xffffff);
+}
+
+#define   IRQ_EN_1__MDP_IRQ___M    0x00000800
+
+void mdp_hw_init(void)
+{
+       int i;
+
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+       /* debug interface write access */
+       outpdw(MDP_BASE + 0x60, 1);
+
+       outp32(MDP_INTR_ENABLE, MDP_ANY_INTR_MASK);
+       outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
+       outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8, 0x0);
+       outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc, 0x0);
+       outpdw(MDP_BASE + 0x60, 0x1);
+       mdp_load_lut_param();
+
+       /*
+        * clear up unused fg/main registers
+        */
+       /* comp.plane 2&3 ystride */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0120, 0x0);
+       /* unpacked pattern */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x012c, 0x0);
+       /* unpacked pattern */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0130, 0x0);
+       /* unpacked pattern */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0134, 0x0);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0158, 0x0);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x15c, 0x0);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0160, 0x0);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0170, 0x0);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0174, 0x0);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x017c, 0x0);
+
+       /* comp.plane 2 */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0114, 0x0);
+       /* comp.plane 3 */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0118, 0x0);
+
+       /* clear up unused bg registers */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8, 0);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0, 0);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc, 0);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0, 0);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4, 0);
+
+#ifndef CONFIG_FB_MSM_MDP22
+       MDP_OUTP(MDP_BASE + 0xE0000, 0);
+       MDP_OUTP(MDP_BASE + 0x100, 0xffffffff);
+       MDP_OUTP(MDP_BASE + 0x90070, 0);
+       MDP_OUTP(MDP_BASE + 0x94010, 1);
+       MDP_OUTP(MDP_BASE + 0x9401c, 2);
+#endif
+
+       /*
+        * limit vector
+        * pre gets applied before color matrix conversion
+        * post is after ccs
+        */
+       writel(mdp_plv[0], MDP_CSC_PRE_LV1n(0));
+       writel(mdp_plv[1], MDP_CSC_PRE_LV1n(1));
+       writel(mdp_plv[2], MDP_CSC_PRE_LV1n(2));
+       writel(mdp_plv[3], MDP_CSC_PRE_LV1n(3));
+
+#ifdef CONFIG_FB_MSM_MDP31
+       writel(mdp_plv[2], MDP_CSC_PRE_LV1n(4));
+       writel(mdp_plv[3], MDP_CSC_PRE_LV1n(5));
+
+       writel(0, MDP_CSC_POST_LV1n(0));
+       writel(0xff, MDP_CSC_POST_LV1n(1));
+       writel(0, MDP_CSC_POST_LV1n(2));
+       writel(0xff, MDP_CSC_POST_LV1n(3));
+       writel(0, MDP_CSC_POST_LV1n(4));
+       writel(0xff, MDP_CSC_POST_LV1n(5));
+
+       writel(0, MDP_CSC_PRE_LV2n(0));
+       writel(0xff, MDP_CSC_PRE_LV2n(1));
+       writel(0, MDP_CSC_PRE_LV2n(2));
+       writel(0xff, MDP_CSC_PRE_LV2n(3));
+       writel(0, MDP_CSC_PRE_LV2n(4));
+       writel(0xff, MDP_CSC_PRE_LV2n(5));
+
+       writel(mdp_plv[0], MDP_CSC_POST_LV2n(0));
+       writel(mdp_plv[1], MDP_CSC_POST_LV2n(1));
+       writel(mdp_plv[2], MDP_CSC_POST_LV2n(2));
+       writel(mdp_plv[3], MDP_CSC_POST_LV2n(3));
+       writel(mdp_plv[2], MDP_CSC_POST_LV2n(4));
+       writel(mdp_plv[3], MDP_CSC_POST_LV2n(5));
+#endif
+
+       /* primary forward matrix */
+       for (i = 0; i < MDP_CCS_SIZE; i++)
+               writel(mdp_ccs_rgb2yuv.ccs[i], MDP_CSC_PFMVn(i));
+
+#ifdef CONFIG_FB_MSM_MDP31
+       for (i = 0; i < MDP_BV_SIZE; i++)
+               writel(mdp_ccs_rgb2yuv.bv[i], MDP_CSC_POST_BV2n(i));
+
+       writel(0, MDP_CSC_PRE_BV2n(0));
+       writel(0, MDP_CSC_PRE_BV2n(1));
+       writel(0, MDP_CSC_PRE_BV2n(2));
+#endif
+       /* primary reverse matrix */
+       for (i = 0; i < MDP_CCS_SIZE; i++)
+               writel(mdp_ccs_yuv2rgb.ccs[i], MDP_CSC_PRMVn(i));
+
+       for (i = 0; i < MDP_BV_SIZE; i++)
+               writel(mdp_ccs_yuv2rgb.bv[i], MDP_CSC_PRE_BV1n(i));
+
+#ifdef CONFIG_FB_MSM_MDP31
+       writel(0, MDP_CSC_POST_BV1n(0));
+       writel(0, MDP_CSC_POST_BV1n(1));
+       writel(0, MDP_CSC_POST_BV1n(2));
+
+       outpdw(MDP_BASE + 0x30010, 0x03e0);
+       outpdw(MDP_BASE + 0x30014, 0x0360);
+       outpdw(MDP_BASE + 0x30018, 0x0120);
+       outpdw(MDP_BASE + 0x3001c, 0x0140);
+#endif
+       mdp_init_scale_table();
+
+#ifndef CONFIG_FB_MSM_MDP31
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0104,
+                ((16 << 6) << 16) | (16) << 6);
+#endif
+
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
\ No newline at end of file
diff --git a/drivers/staging/msm/mdp_ppp.c b/drivers/staging/msm/mdp_ppp.c
new file mode 100644 (file)
index 0000000..c35a6ae
--- /dev/null
@@ -0,0 +1,1502 @@
+/* drivers/video/msm/src/drv/mdp/mdp_ppp.c
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2008-2010, Code Aurora Forum. 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/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <msm_mdp.h>
+#include <linux/file.h>
+#include <linux/major.h>
+
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+#define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \
+                               (((x) < MDP_IMGTYPE2_START) || \
+                                ((x) >= MDP_IMGTYPE_LIMIT2)))
+
+static uint32_t bytes_per_pixel[] = {
+       [MDP_RGB_565] = 2,
+       [MDP_RGB_888] = 3,
+       [MDP_XRGB_8888] = 4,
+       [MDP_ARGB_8888] = 4,
+       [MDP_RGBA_8888] = 4,
+       [MDP_BGRA_8888] = 4,
+       [MDP_Y_CBCR_H2V1] = 1,
+       [MDP_Y_CBCR_H2V2] = 1,
+       [MDP_Y_CRCB_H2V1] = 1,
+       [MDP_Y_CRCB_H2V2] = 1,
+       [MDP_YCRYCB_H2V1] = 2,
+       [MDP_BGR_565] = 2
+};
+
+extern uint32 mdp_plv[];
+extern struct semaphore mdp_ppp_mutex;
+
+uint32_t mdp_get_bytes_per_pixel(uint32_t format)
+{
+       uint32_t bpp = 0;
+       if (format < ARRAY_SIZE(bytes_per_pixel))
+               bpp = bytes_per_pixel[format];
+
+       BUG_ON(!bpp);
+       return bpp;
+}
+
+static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel,
+                                   uint16 *matrix_and_bias_vector,
+                                   uint32 *clamp_vector,
+                                   uint32 *look_up_table)
+{
+       uint8 input_C2, input_C0, input_C1;
+       uint32 output;
+       int32 comp_C2, comp_C1, comp_C0, temp;
+       int32 temp1, temp2, temp3;
+       int32 matrix[9];
+       int32 bias_vector[3];
+       int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
+       int32 i;
+       uint32 _is_lookup_table_enabled;
+
+       input_C2 = (input_pixel >> 16) & 0xFF;
+       input_C1 = (input_pixel >> 8) & 0xFF;
+       input_C0 = (input_pixel >> 0) & 0xFF;
+
+       comp_C0 = input_C0;
+       comp_C1 = input_C1;
+       comp_C2 = input_C2;
+
+       for (i = 0; i < 9; i++)
+               matrix[i] =
+                   ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
+
+       bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
+       bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
+       bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
+
+       Y_low_limit = (int32) clamp_vector[0];
+       Y_high_limit = (int32) clamp_vector[1];
+       C_low_limit = (int32) clamp_vector[2];
+       C_high_limit = (int32) clamp_vector[3];
+
+       if (look_up_table == 0) /* check for NULL point */
+               _is_lookup_table_enabled = 0;
+       else
+               _is_lookup_table_enabled = 1;
+
+       if (_is_lookup_table_enabled == 1) {
+               comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
+               comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
+               comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
+       }
+       /*
+        * Color Conversion
+        * reorder input colors
+        */
+       temp = comp_C2;
+       comp_C2 = comp_C1;
+       comp_C1 = comp_C0;
+       comp_C0 = temp;
+
+       /* matrix multiplication */
+       temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
+       temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
+       temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
+
+       comp_C0 = temp1 + 0x100;
+       comp_C1 = temp2 + 0x100;
+       comp_C2 = temp3 + 0x100;
+
+       /* take interger part */
+       comp_C0 >>= 9;
+       comp_C1 >>= 9;
+       comp_C2 >>= 9;
+
+       /* post bias (+) */
+       comp_C0 += bias_vector[0];
+       comp_C1 += bias_vector[1];
+       comp_C2 += bias_vector[2];
+
+       /* limit pixel to 8-bit */
+       if (comp_C0 < 0)
+               comp_C0 = 0;
+
+       if (comp_C0 > 255)
+               comp_C0 = 255;
+
+       if (comp_C1 < 0)
+               comp_C1 = 0;
+
+       if (comp_C1 > 255)
+               comp_C1 = 255;
+
+       if (comp_C2 < 0)
+               comp_C2 = 0;
+
+       if (comp_C2 > 255)
+               comp_C2 = 255;
+
+       /* clamp */
+       if (comp_C0 < Y_low_limit)
+               comp_C0 = Y_low_limit;
+
+       if (comp_C0 > Y_high_limit)
+               comp_C0 = Y_high_limit;
+
+       if (comp_C1 < C_low_limit)
+               comp_C1 = C_low_limit;
+
+       if (comp_C1 > C_high_limit)
+               comp_C1 = C_high_limit;
+
+       if (comp_C2 < C_low_limit)
+               comp_C2 = C_low_limit;
+
+       if (comp_C2 > C_high_limit)
+               comp_C2 = C_high_limit;
+
+       output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
+       return output;
+}
+
+uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel,
+                            uint16 *matrix_and_bias_vector,
+                            uint32 *clamp_vector, uint32 *look_up_table)
+{
+       uint8 input_C2, input_C0, input_C1;
+       uint32 output;
+       int32 comp_C2, comp_C1, comp_C0, temp;
+       int32 temp1, temp2, temp3;
+       int32 matrix[9];
+       int32 bias_vector[3];
+       int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
+       int32 i;
+       uint32 _is_lookup_table_enabled;
+
+       input_C2 = (input_pixel >> 16) & 0xFF;
+       input_C1 = (input_pixel >> 8) & 0xFF;
+       input_C0 = (input_pixel >> 0) & 0xFF;
+
+       comp_C0 = input_C0;
+       comp_C1 = input_C1;
+       comp_C2 = input_C2;
+
+       for (i = 0; i < 9; i++)
+               matrix[i] =
+                   ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
+
+       bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
+       bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
+       bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
+
+       Y_low_limit = (int32) clamp_vector[0];
+       Y_high_limit = (int32) clamp_vector[1];
+       C_low_limit = (int32) clamp_vector[2];
+       C_high_limit = (int32) clamp_vector[3];
+
+       if (look_up_table == 0) /* check for NULL point */
+               _is_lookup_table_enabled = 0;
+       else
+               _is_lookup_table_enabled = 1;
+
+       /* clamp */
+       if (comp_C0 < Y_low_limit)
+               comp_C0 = Y_low_limit;
+
+       if (comp_C0 > Y_high_limit)
+               comp_C0 = Y_high_limit;
+
+       if (comp_C1 < C_low_limit)
+               comp_C1 = C_low_limit;
+
+       if (comp_C1 > C_high_limit)
+               comp_C1 = C_high_limit;
+
+       if (comp_C2 < C_low_limit)
+               comp_C2 = C_low_limit;
+
+       if (comp_C2 > C_high_limit)
+               comp_C2 = C_high_limit;
+
+       /*
+        * Color Conversion
+        * pre bias (-)
+        */
+       comp_C0 -= bias_vector[0];
+       comp_C1 -= bias_vector[1];
+       comp_C2 -= bias_vector[2];
+
+       /* matrix multiplication */
+       temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
+       temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
+       temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
+
+       comp_C0 = temp1 + 0x100;
+       comp_C1 = temp2 + 0x100;
+       comp_C2 = temp3 + 0x100;
+
+       /* take interger part */
+       comp_C0 >>= 9;
+       comp_C1 >>= 9;
+       comp_C2 >>= 9;
+
+       /* reorder output colors */
+       temp = comp_C0;
+       comp_C0 = comp_C1;
+       comp_C1 = comp_C2;
+       comp_C2 = temp;
+
+       /* limit pixel to 8-bit */
+       if (comp_C0 < 0)
+               comp_C0 = 0;
+
+       if (comp_C0 > 255)
+               comp_C0 = 255;
+
+       if (comp_C1 < 0)
+               comp_C1 = 0;
+
+       if (comp_C1 > 255)
+               comp_C1 = 255;
+
+       if (comp_C2 < 0)
+               comp_C2 = 0;
+
+       if (comp_C2 > 255)
+               comp_C2 = 255;
+
+       /* Look-up table */
+       if (_is_lookup_table_enabled == 1) {
+               comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
+               comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
+               comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
+       }
+
+       output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
+       return output;
+}
+
+static uint32 mdp_calc_tpval(MDPIMG *mdpImg)
+{
+       uint32 tpVal;
+       uint8 plane_tp;
+
+       tpVal = 0;
+       if ((mdpImg->imgType == MDP_RGB_565)
+           || (mdpImg->imgType == MDP_BGR_565)) {
+               /*
+                * transparent color conversion into 24 bpp
+                *
+                * C2R_8BIT
+                * left shift the entire bit and or it with the upper most bits
+                */
+               plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11);
+               tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16;
+
+               /* C1B_8BIT */
+               plane_tp = (uint8) (mdpImg->tpVal & 0x1F);
+               tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8;
+
+               /* C0G_8BIT */
+               plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5);
+               tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4));
+       } else {
+               /* 24bit RGB to RBG conversion */
+
+               tpVal = (mdpImg->tpVal & 0xFF00) >> 8;
+               tpVal |= (mdpImg->tpVal & 0xFF) << 8;
+               tpVal |= (mdpImg->tpVal & 0xFF0000);
+       }
+
+       return tpVal;
+}
+
+static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf)
+{
+       uint8 *dest1;
+
+       dest1 = NULL;
+       switch (iBuf->ibuf_type) {
+       case MDP_Y_CBCR_H2V2:
+       case MDP_Y_CRCB_H2V2:
+       case MDP_Y_CBCR_H2V1:
+       case MDP_Y_CRCB_H2V1:
+               dest1 = (uint8 *) iBuf->buf;
+               dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp;
+               break;
+
+       default:
+               break;
+       }
+
+       return dest1;
+}
+
+static void mdp_ppp_setbg(MDPIBUF *iBuf)
+{
+       uint8 *bg0_addr;
+       uint8 *bg1_addr;
+       uint32 bg0_ystride, bg1_ystride;
+       uint32 ppp_src_cfg_reg, unpack_pattern;
+       int v_slice, h_slice;
+
+       v_slice = h_slice = 1;
+       bg0_addr = (uint8 *) iBuf->buf;
+       bg1_addr = mdp_get_chroma_addr(iBuf);
+
+       bg0_ystride = iBuf->ibuf_width * iBuf->bpp;
+       bg1_ystride = iBuf->ibuf_width * iBuf->bpp;
+
+       switch (iBuf->ibuf_type) {
+       case MDP_BGR_565:
+       case MDP_RGB_565:
+               /* 888 = 3bytes
+                * RGB = 3Components
+                * RGB interleaved
+                */
+               ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
+                       PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+                       PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+                       PPP_SRC_UNPACK_ALIGN_LSB |
+                       PPP_SRC_FETCH_PLANES_INTERLVD;
+
+               if (iBuf->ibuf_type == MDP_RGB_565)
+                       unpack_pattern =
+                           MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+               else
+                       unpack_pattern =
+                           MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+               break;
+
+       case MDP_RGB_888:
+               /*
+                * 888 = 3bytes
+                * RGB = 3Components
+                * RGB interleaved
+                */
+               ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+               PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
+               PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+               PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD;
+
+               unpack_pattern =
+                   MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+               break;
+
+       case MDP_BGRA_8888:
+       case MDP_RGBA_8888:
+       case MDP_ARGB_8888:
+       case MDP_XRGB_8888:
+               /*
+                * 8888 = 4bytes
+                * ARGB = 4Components
+                * ARGB interleaved
+                */
+               ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+               PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | PPP_SRC_C3_ALPHA_EN |
+               PPP_SRC_BPP_INTERLVD_4BYTES | PPP_SRC_INTERLVD_4COMPONENTS |
+               PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB |
+               PPP_SRC_FETCH_PLANES_INTERLVD;
+
+               if (iBuf->ibuf_type == MDP_BGRA_8888)
+                       unpack_pattern =
+                           MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+                                                8);
+               else if (iBuf->ibuf_type == MDP_RGBA_8888)
+                       unpack_pattern =
+                           MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+                                                8);
+               else
+                       unpack_pattern =
+                           MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+                                                8);
+               break;
+
+       case MDP_Y_CBCR_H2V2:
+       case MDP_Y_CRCB_H2V2:
+               ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+                   PPP_SRC_C0G_8BITS |
+                   PPP_SRC_C1B_8BITS |
+                   PPP_SRC_C3A_8BITS |
+                   PPP_SRC_BPP_INTERLVD_2BYTES |
+                   PPP_SRC_INTERLVD_2COMPONENTS |
+                   PPP_SRC_UNPACK_TIGHT |
+                   PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+               if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+                       unpack_pattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+               else
+                       unpack_pattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+               v_slice = h_slice = 2;
+               break;
+
+       case MDP_YCRYCB_H2V1:
+               ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+                   PPP_SRC_C0G_8BITS |
+                   PPP_SRC_C1B_8BITS |
+                   PPP_SRC_C3A_8BITS |
+                   PPP_SRC_BPP_INTERLVD_2BYTES |
+                   PPP_SRC_INTERLVD_4COMPONENTS |
+                   PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
+
+               unpack_pattern =
+                   MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+               h_slice = 2;
+               break;
+
+       case MDP_Y_CBCR_H2V1:
+       case MDP_Y_CRCB_H2V1:
+               ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+                   PPP_SRC_C0G_8BITS |
+                   PPP_SRC_C1B_8BITS |
+                   PPP_SRC_C3A_8BITS |
+                   PPP_SRC_BPP_INTERLVD_2BYTES |
+                   PPP_SRC_INTERLVD_2COMPONENTS |
+                   PPP_SRC_UNPACK_TIGHT |
+                   PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+               if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+                       unpack_pattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+               else
+                       unpack_pattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+               h_slice = 2;
+               break;
+
+       default:
+               return;
+       }
+
+       /* starting input address adjustment */
+       mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice,
+                             iBuf->roi.lcd_x, iBuf->roi.lcd_y,
+                             iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
+                             iBuf, 1);
+
+       /*
+        * 0x01c0: background plane 0 addr
+        * 0x01c4: background plane 1 addr
+        * 0x01c8: background plane 2 addr
+        * 0x01cc: bg y stride for plane 0 and 1
+        * 0x01d0: bg y stride for plane 2
+        * 0x01d4: bg src PPP config
+        * 0x01d8: unpack pattern
+        */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr);
+
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc,
+                (bg1_ystride << 16) | bg0_ystride);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg);
+
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern);
+}
+
+#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
+                               (img == MDP_Y_CBCR_H2V2) | \
+                               (img == MDP_Y_CRCB_H2V1) | \
+                               (img == MDP_Y_CBCR_H2V1))
+
+#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
+
+#define Y_TO_CRCB_RATIO(format) \
+       ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ?  2 :\
+       (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ?  1 : 1)
+
+static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
+                       uint32_t *len0, uint32_t *len1)
+{
+       *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
+       if (IS_PSEUDOPLNR(img->format))
+               *len1 = *len0/Y_TO_CRCB_RATIO(img->format);
+       else
+               *len1 = 0;
+}
+
+static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp,
+                       struct file *p_src_file, struct file *p_dst_file)
+{
+#ifdef CONFIG_ANDROID_PMEM
+       uint32_t src0_len, src1_len, dst0_len, dst1_len;
+
+       /* flush src images to memory before dma to mdp */
+       get_len(&req->src, &req->src_rect, src_bpp,
+       &src0_len, &src1_len);
+
+       flush_pmem_file(p_src_file,
+       req->src.offset, src0_len);
+
+       if (IS_PSEUDOPLNR(req->src.format))
+               flush_pmem_file(p_src_file,
+                       req->src.offset + src0_len, src1_len);
+
+       get_len(&req->dst, &req->dst_rect, dst_bpp, &dst0_len, &dst1_len);
+       flush_pmem_file(p_dst_file, req->dst.offset, dst0_len);
+
+       if (IS_PSEUDOPLNR(req->dst.format))
+               flush_pmem_file(p_dst_file,
+                       req->dst.offset + dst0_len, dst1_len);
+#endif
+}
+
+static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf,
+struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file)
+{
+       uint8 *src0, *src1;
+       uint8 *dest0, *dest1;
+       uint16 inpBpp;
+       uint32 dest0_ystride;
+       uint32 src_width;
+       uint32 src_height;
+       uint32 src0_ystride;
+       uint32 dst_roi_width;
+       uint32 dst_roi_height;
+       uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg;
+       uint32 alpha, tpVal;
+       uint32 packPattern;
+       uint32 dst_packPattern;
+       boolean inputRGB, outputRGB, pseudoplanr_output;
+       int sv_slice, sh_slice;
+       int dv_slice, dh_slice;
+       boolean perPixelAlpha = FALSE;
+       boolean ppp_lookUp_enable = FALSE;
+
+       sv_slice = sh_slice = dv_slice = dh_slice = 1;
+       alpha = tpVal = 0;
+       src_width = iBuf->mdpImg.width;
+       src_height = iBuf->roi.y + iBuf->roi.height;
+       src1 = NULL;
+       dest1 = NULL;
+
+       inputRGB = outputRGB = TRUE;
+       pseudoplanr_output = FALSE;
+       ppp_operation_reg = 0;
+       ppp_dst_cfg_reg = 0;
+       ppp_src_cfg_reg = 0;
+
+       /* Wait for the pipe to clear */
+       do { } while (mdp_ppp_pipe_wait() <= 0);
+
+       /*
+        * destination config
+        */
+       switch (iBuf->ibuf_type) {
+       case MDP_RGB_888:
+               dst_packPattern =
+                   MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+               ppp_dst_cfg_reg =
+                   PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT |
+                   PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT |
+                   PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI |
+                   PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD;
+               break;
+
+       case MDP_XRGB_8888:
+       case MDP_ARGB_8888:
+       case MDP_RGBA_8888:
+               if (iBuf->ibuf_type == MDP_BGRA_8888)
+                       dst_packPattern =
+                           MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+                                                8);
+               else if (iBuf->ibuf_type == MDP_RGBA_8888)
+                       dst_packPattern =
+                           MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+                                                8);
+               else
+                       dst_packPattern =
+                           MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+                                                8);
+
+               ppp_dst_cfg_reg = PPP_DST_C0G_8BIT |
+                   PPP_DST_C1B_8BIT |
+                   PPP_DST_C2R_8BIT |
+                   PPP_DST_C3A_8BIT |
+                   PPP_DST_C3ALPHA_EN |
+                   PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
+                   PPP_DST_PACK_TIGHT |
+                   PPP_DST_PACK_ALIGN_LSB |
+                   PPP_DST_OUT_SEL_AXI |
+                   PPP_DST_BPP_4BYTES | PPP_DST_PLANE_INTERLVD;
+               break;
+
+       case MDP_Y_CBCR_H2V2:
+       case MDP_Y_CRCB_H2V2:
+               if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2)
+                       dst_packPattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+               else
+                       dst_packPattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+               ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
+                   PPP_DST_C0G_8BIT |
+                   PPP_DST_C1B_8BIT |
+                   PPP_DST_C3A_8BIT |
+                   PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
+                   PPP_DST_PACK_TIGHT |
+                   PPP_DST_PACK_ALIGN_LSB |
+                   PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
+
+               ppp_operation_reg |= PPP_OP_DST_CHROMA_420;
+               outputRGB = FALSE;
+               pseudoplanr_output = TRUE;
+               /*
+                * vertically (y direction) and horizontally (x direction)
+                * sample reduction by 2
+                */
+
+               /*
+                * H2V2(YUV420) Cosite
+                *
+                * Y    Y    Y    Y
+                * CbCr      CbCr
+                * Y    Y    Y    Y
+                * Y    Y    Y    Y
+                * CbCr      CbCr
+                * Y    Y    Y    Y
+                */
+               dv_slice = dh_slice = 2;
+
+               /* (x,y) and (width,height) must be even numbern */
+               iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+               iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+               iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+               iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+
+               iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2;
+               iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2;
+               iBuf->roi.y = (iBuf->roi.y / 2) * 2;
+               iBuf->roi.height = (iBuf->roi.height / 2) * 2;
+               break;
+
+       case MDP_YCRYCB_H2V1:
+               dst_packPattern =
+                   MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+               ppp_dst_cfg_reg =
+                   PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT |
+                   PPP_DST_C3A_8BIT | PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
+                   PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB |
+                   PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES |
+                   PPP_DST_PLANE_INTERLVD;
+
+               ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
+               outputRGB = FALSE;
+               /*
+                * horizontally (x direction) sample reduction by 2
+                *
+                * H2V1(YUV422) Cosite
+                *
+                * YCbCr    Y    YCbCr    Y
+                * YCbCr    Y    YCbCr    Y
+                * YCbCr    Y    YCbCr    Y
+                * YCbCr    Y    YCbCr    Y
+                */
+               dh_slice = 2;
+
+               /*
+                * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
+                * preloaded gamma setting of 2.2 when the content is
+                * non-linear ppp_lookUp_enable = TRUE;
+                */
+
+               /* x and width must be even number */
+               iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+               iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+               iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+               iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+               break;
+
+       case MDP_Y_CBCR_H2V1:
+       case MDP_Y_CRCB_H2V1:
+               if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+                       dst_packPattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+               else
+                       dst_packPattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+               ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
+                   PPP_DST_C0G_8BIT |
+                   PPP_DST_C1B_8BIT |
+                   PPP_DST_C3A_8BIT |
+                   PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
+                   PPP_DST_PACK_TIGHT |
+                   PPP_DST_PACK_ALIGN_LSB |
+                   PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
+
+               ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
+               outputRGB = FALSE;
+               pseudoplanr_output = TRUE;
+               /* horizontally (x direction) sample reduction by 2 */
+               dh_slice = 2;
+
+               /* x and width must be even number */
+               iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+               iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+               iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+               iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+               break;
+
+       case MDP_BGR_565:
+       case MDP_RGB_565:
+       default:
+               if (iBuf->ibuf_type == MDP_RGB_565)
+                       dst_packPattern =
+                           MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+               else
+                       dst_packPattern =
+                           MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+
+               ppp_dst_cfg_reg = PPP_DST_C0G_6BIT |
+                   PPP_DST_C1B_5BIT |
+                   PPP_DST_C2R_5BIT |
+                   PPP_DST_PACKET_CNT_INTERLVD_3ELEM |
+                   PPP_DST_PACK_TIGHT |
+                   PPP_DST_PACK_ALIGN_LSB |
+                   PPP_DST_OUT_SEL_AXI |
+                   PPP_DST_BPP_2BYTES | PPP_DST_PLANE_INTERLVD;
+               break;
+       }
+
+       /* source config */
+       switch (iBuf->mdpImg.imgType) {
+       case MDP_RGB_888:
+               inpBpp = 3;
+               /*
+                * 565 = 2bytes
+                * RGB = 3Components
+                * RGB interleaved
+                */
+               ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+                       PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
+                       PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+                       PPP_SRC_UNPACK_ALIGN_LSB |
+                       PPP_SRC_FETCH_PLANES_INTERLVD;
+
+               packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+
+               ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+                   PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+               break;
+
+       case MDP_BGRA_8888:
+       case MDP_RGBA_8888:
+       case MDP_ARGB_8888:
+               perPixelAlpha = TRUE;
+       case MDP_XRGB_8888:
+               inpBpp = 4;
+               /*
+                * 8888 = 4bytes
+                * ARGB = 4Components
+                * ARGB interleaved
+                */
+               ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+                       PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS |
+                       PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES |
+                       PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+                       PPP_SRC_UNPACK_ALIGN_LSB |
+                       PPP_SRC_FETCH_PLANES_INTERLVD;
+
+               if (iBuf->mdpImg.imgType == MDP_BGRA_8888)
+                       packPattern =
+                           MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+                                                8);
+               else if (iBuf->mdpImg.imgType == MDP_RGBA_8888)
+                       packPattern =
+                           MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+                                                8);
+               else
+                       packPattern =
+                           MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+                                                8);
+
+               ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+                   PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+               break;
+
+       case MDP_Y_CBCR_H2V2:
+       case MDP_Y_CRCB_H2V2:
+               inpBpp = 1;
+               src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
+
+               /*
+                * CbCr = 2bytes
+                * CbCr = 2Components
+                * Y+CbCr
+                */
+               ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+                       PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+                       PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+                       PPP_SRC_UNPACK_ALIGN_LSB |
+                       PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+               if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2)
+                       packPattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+               else
+                       packPattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+
+               ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR |
+                   PPP_OP_SRC_CHROMA_420 |
+                   PPP_OP_SRC_CHROMA_COSITE |
+                   PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE;
+
+               inputRGB = FALSE;
+               sh_slice = sv_slice = 2;
+               break;
+
+       case MDP_YCRYCB_H2V1:
+               inpBpp = 2;
+               ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+                   PPP_SRC_C0G_8BITS |
+                   PPP_SRC_C1B_8BITS |
+                   PPP_SRC_C3A_8BITS |
+                   PPP_SRC_BPP_INTERLVD_2BYTES |
+                   PPP_SRC_INTERLVD_4COMPONENTS |
+                   PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
+
+               packPattern =
+                   MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+
+               ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
+                   PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
+
+               /*
+                * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
+                * preloaded inverse gamma setting of 2.2 since they're
+                * symetric when the content is non-linear
+                * ppp_lookUp_enable = TRUE;
+                */
+
+               /* x and width must be even number */
+               iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+               iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+               iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+               iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+
+               inputRGB = FALSE;
+               sh_slice = 2;
+               break;
+
+       case MDP_Y_CBCR_H2V1:
+       case MDP_Y_CRCB_H2V1:
+               inpBpp = 1;
+               src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
+
+               ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+                   PPP_SRC_C0G_8BITS |
+                   PPP_SRC_C1B_8BITS |
+                   PPP_SRC_C3A_8BITS |
+                   PPP_SRC_BPP_INTERLVD_2BYTES |
+                   PPP_SRC_INTERLVD_2COMPONENTS |
+                   PPP_SRC_UNPACK_TIGHT |
+                   PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+               if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1)
+                       packPattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+               else
+                       packPattern =
+                           MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+               ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
+                   PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
+               inputRGB = FALSE;
+               sh_slice = 2;
+               break;
+
+       case MDP_BGR_565:
+       case MDP_RGB_565:
+       default:
+               inpBpp = 2;
+               /*
+                * 565 = 2bytes
+                * RGB = 3Components
+                * RGB interleaved
+                */
+               ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
+                       PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+                       PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+                       PPP_SRC_UNPACK_ALIGN_LSB |
+                       PPP_SRC_FETCH_PLANES_INTERLVD;
+
+               if (iBuf->mdpImg.imgType == MDP_RGB_565)
+                       packPattern =
+                           MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+               else
+                       packPattern =
+                           MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+
+               ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+                   PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+               break;
+
+       }
+
+       if (pseudoplanr_output)
+               ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN;
+
+       /* YCbCr to RGB color conversion flag */
+       if ((!inputRGB) && (outputRGB)) {
+               ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB |
+                   PPP_OP_CONVERT_ON;
+
+               /*
+                * primary/secondary is sort of misleading term...but
+                * in mdp2.2/3.0 we only use primary matrix (forward/rev)
+                * in mdp3.1 we use set1(prim) and set2(secd)
+                */
+#ifdef CONFIG_FB_MSM_MDP31
+               ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY |
+                                       PPP_OP_DST_RGB;
+               MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0);
+#endif
+
+               if (ppp_lookUp_enable) {
+                       ppp_operation_reg |= PPP_OP_LUT_C0_ON |
+                           PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
+               }
+       }
+       /* RGB to YCbCr color conversion flag */
+       if ((inputRGB) && (!outputRGB)) {
+               ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR |
+                   PPP_OP_CONVERT_ON;
+
+#ifdef CONFIG_FB_MSM_MDP31
+               ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY |
+                                       PPP_OP_DST_YCBCR;
+               MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e);
+#endif
+
+               if (ppp_lookUp_enable) {
+                       ppp_operation_reg |= PPP_OP_LUT_C0_ON |
+                           PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
+               }
+       }
+       /* YCbCr to YCbCr color conversion flag */
+       if ((!inputRGB) && (!outputRGB)) {
+               if ((ppp_lookUp_enable) &&
+                   (iBuf->mdpImg.imgType != iBuf->ibuf_type)) {
+                       ppp_operation_reg |= PPP_OP_LUT_C0_ON;
+               }
+       }
+
+       ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0;
+       ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
+
+       if (req->flags & MDP_DEINTERLACE)
+               ppp_operation_reg |= PPP_OP_DEINT_EN;
+
+       /* Dither at DMA side only since iBuf format is RGB888 */
+       if (iBuf->mdpImg.mdpOp & MDPOP_DITHER)
+               ppp_operation_reg |= PPP_OP_DITHER_EN;
+
+       if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) {
+               ppp_operation_reg |= PPP_OP_ROT_ON;
+
+               if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+                       ppp_operation_reg |= PPP_OP_ROT_90;
+               }
+               if (iBuf->mdpImg.mdpOp & MDPOP_LR) {
+                       ppp_operation_reg |= PPP_OP_FLIP_LR;
+               }
+               if (iBuf->mdpImg.mdpOp & MDPOP_UD) {
+                       ppp_operation_reg |= PPP_OP_FLIP_UD;
+               }
+       }
+
+       src0_ystride = src_width * inpBpp;
+       dest0_ystride = iBuf->ibuf_width * iBuf->bpp;
+
+       /* no need to care about rotation since it's the real-XY. */
+       dst_roi_width = iBuf->roi.dst_width;
+       dst_roi_height = iBuf->roi.dst_height;
+
+       src0 = (uint8 *) iBuf->mdpImg.bmy_addr;
+       dest0 = (uint8 *) iBuf->buf;
+
+       /* Jumping from Y-Plane to Chroma Plane */
+       dest1 = mdp_get_chroma_addr(iBuf);
+
+       /* first pixel addr calculation */
+       mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x,
+                             iBuf->roi.y, src_width, src_height, inpBpp, iBuf,
+                             0);
+       mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice,
+                             iBuf->roi.lcd_x, iBuf->roi.lcd_y,
+                             iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
+                             iBuf, 2);
+
+       /* set scale operation */
+       mdp_set_scale(iBuf, dst_roi_width, dst_roi_height,
+                     inputRGB, outputRGB, &ppp_operation_reg);
+
+       /*
+        * setting background source for blending
+        */
+       mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha,
+                          &ppp_operation_reg);
+
+       if (ppp_operation_reg & PPP_OP_BLEND_ON) {
+               mdp_ppp_setbg(iBuf);
+
+               if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
+                       ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1;
+
+                       if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
+                               tpVal = mdp_conv_matx_rgb2yuv(tpVal,
+                                                     (uint16 *) &
+                                                     mdp_ccs_rgb2yuv,
+                                                     &mdp_plv[0], NULL);
+                       }
+               }
+       }
+
+       /*
+        * 0x0004: enable dbg bus
+        * 0x0100: "don't care" Edge Condit until scaling is on
+        * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit
+        * 0x0108: src pixel size
+        * 0x010c: component plane 0 starting address
+        * 0x011c: component plane 0 ystride
+        * 0x0124: PPP source config register
+        * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR)
+        */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 |
+                                                     iBuf->roi.width));
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c,
+                (src0_ystride << 16 | src0_ystride));
+
+       /* setup for rgb 565 */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern);
+       /*
+        * 0x0138: PPP destination operation register
+        * 0x014c: constant_alpha|transparent_color
+        * 0x0150: PPP destination config register
+        * 0x0154: PPP packing pattern
+        */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | tpVal);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern);
+
+       /*
+        * 0x0164: ROI height and width
+        * 0x0168: Component Plane 0 starting addr
+        * 0x016c: Component Plane 1 starting addr
+        * 0x0178: Component Plane 1/0 y stride
+        */
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164,
+                (dst_roi_height << 16 | dst_roi_width));
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178,
+                (dest0_ystride << 16 | dest0_ystride));
+
+       flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file);
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+       mdp_ppp_process_curr_djob();
+#else
+       mdp_pipe_kickoff(MDP_PPP_TERM, mfd);
+#endif
+}
+
+static int mdp_ppp_verify_req(struct mdp_blit_req *req)
+{
+       u32 src_width, src_height, dst_width, dst_height;
+
+       if (req == NULL)
+               return -1;
+
+       if (MDP_IS_IMGTYPE_BAD(req->src.format) ||
+           MDP_IS_IMGTYPE_BAD(req->dst.format))
+               return -1;
+
+       if ((req->src.width == 0) || (req->src.height == 0) ||
+           (req->src_rect.w == 0) || (req->src_rect.h == 0) ||
+           (req->dst.width == 0) || (req->dst.height == 0) ||
+           (req->dst_rect.w == 0) || (req->dst_rect.h == 0))
+
+               return -1;
+
+       if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
+           ((req->src_rect.y + req->src_rect.h) > req->src.height))
+               return -1;
+
+       if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) ||
+           ((req->dst_rect.y + req->dst_rect.h) > req->dst.height))
+               return -1;
+
+       /*
+        * scaling range check
+        */
+       src_width = req->src_rect.w;
+       src_height = req->src_rect.h;
+
+       if (req->flags & MDP_ROT_90) {
+               dst_width = req->dst_rect.h;
+               dst_height = req->dst_rect.w;
+       } else {
+               dst_width = req->dst_rect.w;
+               dst_height = req->dst_rect.h;
+       }
+
+       switch (req->dst.format) {
+       case MDP_Y_CRCB_H2V2:
+       case MDP_Y_CBCR_H2V2:
+               src_width = (src_width / 2) * 2;
+               src_height = (src_height / 2) * 2;
+               dst_width = (src_width / 2) * 2;
+               dst_height = (src_height / 2) * 2;
+               break;
+
+       case MDP_Y_CRCB_H2V1:
+       case MDP_Y_CBCR_H2V1:
+       case MDP_YCRYCB_H2V1:
+               src_width = (src_width / 2) * 2;
+               dst_width = (src_width / 2) * 2;
+               break;
+
+       default:
+               break;
+       }
+
+       if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width >
+            MDP_MAX_X_SCALE_FACTOR)
+           || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width <
+               MDP_MIN_X_SCALE_FACTOR))
+               return -1;
+
+       if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height >
+            MDP_MAX_Y_SCALE_FACTOR)
+           || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height <
+               MDP_MIN_Y_SCALE_FACTOR))
+               return -1;
+
+       return 0;
+}
+
+/**
+ * get_gem_img() - retrieve drm obj's start address and size
+ * @img:       contains drm file descriptor and gem handle
+ * @start:     repository of starting address of drm obj allocated memory
+ * @len:       repository of size of drm obj alloacted memory
+ *
+ **/
+int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len)
+{
+       panic("waaaaaaaah");
+       //return kgsl_gem_obj_addr(img->memory_id, (int)img->priv, start, len);
+}
+
+int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start,
+           unsigned long *len, struct file **pp_file)
+{
+       int put_needed, ret = 0;
+       struct file *file;
+       unsigned long vstart;
+#ifdef CONFIG_ANDROID_PMEM
+       if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
+               return 0;
+#endif
+       file = fget_light(img->memory_id, &put_needed);
+       if (file == NULL)
+               return -1;
+
+       if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+               *start = info->fix.smem_start;
+               *len = info->fix.smem_len;
+               *pp_file = file;
+       } else {
+               ret = -1;
+               fput_light(file, put_needed);
+       }
+       return ret;
+}
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+       struct file **pp_src_file, struct file **pp_dst_file)
+{
+       unsigned long src_start, dst_start;
+       unsigned long src_len = 0;
+       unsigned long dst_len = 0;
+       MDPIBUF iBuf;
+       u32 dst_width, dst_height;
+       struct file *p_src_file = 0 , *p_dst_file = 0;
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+       if (req->dst.format == MDP_FB_FORMAT)
+               req->dst.format =  mfd->fb_imgType;
+       if (req->src.format == MDP_FB_FORMAT)
+               req->src.format = mfd->fb_imgType;
+
+       if (req->flags & MDP_BLIT_SRC_GEM) {
+               if (get_gem_img(&req->src, &src_start, &src_len) < 0)
+                       return -1;
+       } else {
+               get_img(&req->src, info, &src_start, &src_len, &p_src_file);
+       }
+       if (src_len == 0) {
+               printk(KERN_ERR "mdp_ppp: could not retrieve image from "
+                      "memory\n");
+               return -1;
+       }
+
+       if (req->flags & MDP_BLIT_DST_GEM) {
+               if (get_gem_img(&req->dst, &dst_start, &dst_len) < 0)
+                       return -1;
+       } else {
+               get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file);
+       }
+       if (dst_len == 0) {
+               printk(KERN_ERR "mdp_ppp: could not retrieve image from "
+                      "memory\n");
+               return -1;
+       }
+       *pp_src_file = p_src_file;
+       *pp_dst_file = p_dst_file;
+       if (mdp_ppp_verify_req(req)) {
+               printk(KERN_ERR "mdp_ppp: invalid image!\n");
+               return -1;
+       }
+
+       iBuf.ibuf_width = req->dst.width;
+       iBuf.ibuf_height = req->dst.height;
+       iBuf.bpp = bytes_per_pixel[req->dst.format];
+
+       iBuf.ibuf_type = req->dst.format;
+       iBuf.buf = (uint8 *) dst_start;
+       iBuf.buf += req->dst.offset;
+
+       iBuf.roi.lcd_x = req->dst_rect.x;
+       iBuf.roi.lcd_y = req->dst_rect.y;
+       iBuf.roi.dst_width = req->dst_rect.w;
+       iBuf.roi.dst_height = req->dst_rect.h;
+
+       iBuf.roi.x = req->src_rect.x;
+       iBuf.roi.width = req->src_rect.w;
+       iBuf.roi.y = req->src_rect.y;
+       iBuf.roi.height = req->src_rect.h;
+
+       iBuf.mdpImg.width = req->src.width;
+       iBuf.mdpImg.imgType = req->src.format;
+
+       iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset);
+       iBuf.mdpImg.cbcr_addr =
+           (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+                       req->src.width * req->src.height);
+
+       iBuf.mdpImg.mdpOp = MDPOP_NOP;
+
+       /* blending check */
+       if (req->transp_mask != MDP_TRANSP_NOP) {
+               iBuf.mdpImg.mdpOp |= MDPOP_TRANSP;
+               iBuf.mdpImg.tpVal = req->transp_mask;
+               iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg);
+       }
+
+       req->alpha &= 0xff;
+       if (req->alpha < MDP_ALPHA_NOP) {
+               iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB;
+               iBuf.mdpImg.alpha = req->alpha;
+       }
+
+       /* rotation check */
+       if (req->flags & MDP_FLIP_LR)
+               iBuf.mdpImg.mdpOp |= MDPOP_LR;
+       if (req->flags & MDP_FLIP_UD)
+               iBuf.mdpImg.mdpOp |= MDPOP_UD;
+       if (req->flags & MDP_ROT_90)
+               iBuf.mdpImg.mdpOp |= MDPOP_ROT90;
+       if (req->flags & MDP_DITHER)
+               iBuf.mdpImg.mdpOp |= MDPOP_DITHER;
+
+       if (req->flags & MDP_BLEND_FG_PREMULT) {
+#ifdef CONFIG_FB_MSM_MDP31
+               iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
+#else
+               return -EINVAL;
+#endif
+       }
+
+       if (req->flags & MDP_DEINTERLACE) {
+#ifdef CONFIG_FB_MSM_MDP31
+               if ((req->src.format != MDP_Y_CBCR_H2V2) &&
+                       (req->src.format != MDP_Y_CRCB_H2V2))
+#endif
+               return -EINVAL;
+       }
+
+       /* scale check */
+       if (req->flags & MDP_ROT_90) {
+               dst_width = req->dst_rect.h;
+               dst_height = req->dst_rect.w;
+       } else {
+               dst_width = req->dst_rect.w;
+               dst_height = req->dst_rect.h;
+       }
+
+       if ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height))
+               iBuf.mdpImg.mdpOp |= MDPOP_ASCALE;
+
+       if (req->flags & MDP_BLUR) {
+#ifdef CONFIG_FB_MSM_MDP31
+               if (req->flags & MDP_SHARPENING)
+                       printk(KERN_WARNING
+                               "mdp: MDP_SHARPENING is set with MDP_BLUR!\n");
+               req->flags |= MDP_SHARPENING;
+               req->sharpening_strength = -127;
+#else
+               iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR;
+
+#endif
+       }
+
+       if (req->flags & MDP_SHARPENING) {
+#ifdef CONFIG_FB_MSM_MDP31
+               if ((req->sharpening_strength > 127) ||
+                       (req->sharpening_strength < -127)) {
+                       printk(KERN_ERR
+                               "%s: sharpening strength out of range\n",
+                               __func__);
+                       return -EINVAL;
+               }
+
+               iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING;
+               iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff;
+#else
+               return -EINVAL;
+#endif
+       }
+
+       down(&mdp_ppp_mutex);
+       /* MDP cmd block enable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef CONFIG_FB_MSM_MDP31
+       mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+#else
+       /* bg tile fetching HW workaround */
+       if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
+            (req->src.format == MDP_ARGB_8888) ||
+            (req->src.format == MDP_BGRA_8888) ||
+            (req->src.format == MDP_RGBA_8888)) &&
+           (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) {
+               int dst_h, src_w, i;
+
+               src_w = req->src_rect.w;
+               dst_h = iBuf.roi.dst_height;
+
+               for (i = 0; i < (req->dst_rect.h / 16); i++) {
+                       /* this tile size */
+                       iBuf.roi.dst_height = 16;
+                       iBuf.roi.width =
+                           (16 * req->src_rect.w) / req->dst_rect.h;
+
+                       /* if it's out of scale range... */
+                       if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+                            iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR)
+                               iBuf.roi.width =
+                                   (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+                                   MDP_MAX_X_SCALE_FACTOR;
+                       else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+                                 iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR)
+                               iBuf.roi.width =
+                                   (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+                                   MDP_MIN_X_SCALE_FACTOR;
+
+                       mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+
+                       /* next tile location */
+                       iBuf.roi.lcd_y += 16;
+                       iBuf.roi.x += iBuf.roi.width;
+
+                       /* this is for a remainder update */
+                       dst_h -= 16;
+                       src_w -= iBuf.roi.width;
+               }
+
+               if ((dst_h < 0) || (src_w < 0))
+                       printk
+                           ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n",
+                            __LINE__);
+
+               /* remainder update */
+               if ((dst_h > 0) && (src_w > 0)) {
+                       u32 tmp_v;
+
+                       iBuf.roi.dst_height = dst_h;
+                       iBuf.roi.width = src_w;
+
+                       if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+                            iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) {
+                               tmp_v =
+                                   (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+                                   MDP_MAX_X_SCALE_FACTOR +
+                                   (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
+                                   MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
+
+                               /* move x location as roi width gets bigger */
+                               iBuf.roi.x -= tmp_v - iBuf.roi.width;
+                               iBuf.roi.width = tmp_v;
+                       } else
+                           if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+                                iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) {
+                               tmp_v =
+                                   (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+                                   MDP_MIN_X_SCALE_FACTOR +
+                                   (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
+                                   MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
+
+                               /*
+                                * we don't move x location for continuity of
+                                * source image
+                                */
+                               iBuf.roi.width = tmp_v;
+                       }
+
+                       mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+               }
+       } else {
+               mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+       }
+#endif
+
+       /* MDP cmd block disable */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+       up(&mdp_ppp_mutex);
+
+       return 0;
+}
diff --git a/drivers/staging/msm/mdp_ppp_dq.c b/drivers/staging/msm/mdp_ppp_dq.c
new file mode 100644 (file)
index 0000000..3dc1c0c
--- /dev/null
@@ -0,0 +1,347 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "mdp.h"
+
+static boolean mdp_ppp_intr_flag = FALSE;
+static boolean mdp_ppp_busy_flag = FALSE;
+
+/* Queue to keep track of the completed jobs for cleaning */
+static LIST_HEAD(mdp_ppp_djob_clnrq);
+static DEFINE_SPINLOCK(mdp_ppp_djob_clnrq_lock);
+
+/* Worker to cleanup Display Jobs */
+static struct workqueue_struct *mdp_ppp_djob_clnr;
+
+/* Display Queue (DQ) for MDP PPP Block */
+static LIST_HEAD(mdp_ppp_dq);
+static DEFINE_SPINLOCK(mdp_ppp_dq_lock);
+
+/* Current Display Job for MDP PPP */
+static struct mdp_ppp_djob *curr_djob;
+
+/* Track ret code for the last opeartion */
+static int mdp_ppp_ret_code;
+
+inline int mdp_ppp_get_ret_code(void)
+{
+       return mdp_ppp_ret_code;
+}
+
+/* Push <Reg, Val> pair into DQ (if available) to later
+ * program the MDP PPP Block */
+inline void mdp_ppp_outdw(uint32_t addr, uint32_t data)
+{
+       if (curr_djob) {
+
+               /* get the last node of the list. */
+               struct mdp_ppp_roi_cmd_set *node =
+                       list_entry(curr_djob->roi_cmd_list.prev,
+                               struct mdp_ppp_roi_cmd_set, node);
+
+               /* If a node is already full, create a new one and add it to
+                * the list (roi_cmd_list).
+                */
+               if (node->ncmds == MDP_PPP_ROI_NODE_SIZE) {
+                       node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set),
+                               GFP_KERNEL);
+                       if (!node) {
+                               printk(KERN_ERR
+                                       "MDP_PPP: not enough memory.\n");
+                               mdp_ppp_ret_code = -EINVAL;
+                               return;
+                       }
+
+                       /* no ROI commands initially */
+                       node->ncmds = 0;
+
+                       /* add one node to roi_cmd_list. */
+                       list_add_tail(&node->node, &curr_djob->roi_cmd_list);
+               }
+
+               /* register ROI commands */
+               node->cmd[node->ncmds].reg = addr;
+               node->cmd[node->ncmds].val = data;
+               node->ncmds++;
+       } else
+               /* program MDP PPP block now */
+               outpdw((addr), (data));
+}
+
+/* Initialize DQ */
+inline void mdp_ppp_dq_init(void)
+{
+       mdp_ppp_djob_clnr = create_singlethread_workqueue("MDPDJobClnrThrd");
+}
+
+/* Release resources of a job (DJob). */
+static void mdp_ppp_del_djob(struct mdp_ppp_djob *job)
+{
+       struct mdp_ppp_roi_cmd_set *node, *tmp;
+
+       /* release mem */
+       mdp_ppp_put_img(job->p_src_file, job->p_dst_file);
+
+       /* release roi_cmd_list */
+       list_for_each_entry_safe(node, tmp, &job->roi_cmd_list, node) {
+               list_del(&node->node);
+               kfree(node);
+       }
+
+       /* release job struct */
+       kfree(job);
+}
+
+/* Worker thread to reclaim resources once a display job is done */
+static void mdp_ppp_djob_cleaner(struct work_struct *work)
+{
+       struct mdp_ppp_djob *job;
+
+       MDP_PPP_DEBUG_MSG("mdp ppp display job cleaner started \n");
+
+       /* cleanup display job */
+       job = container_of(work, struct mdp_ppp_djob, cleaner.work);
+       if (likely(work && job))
+               mdp_ppp_del_djob(job);
+}
+
+/* Create a new Display Job (DJob) */
+inline struct mdp_ppp_djob *mdp_ppp_new_djob(void)
+{
+       struct mdp_ppp_djob *job;
+       struct mdp_ppp_roi_cmd_set *node;
+
+       /* create a new djob */
+       job = kmalloc(sizeof(struct mdp_ppp_djob), GFP_KERNEL);
+       if (!job)
+               return NULL;
+
+       /* add the first node to curr_djob->roi_cmd_list */
+       node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set), GFP_KERNEL);
+       if (!node) {
+               kfree(job);
+               return NULL;
+       }
+
+       /* make this current djob container to keep track of the curr djob not
+        * used in the async path i.e. no sync needed
+        *
+        * Should not contain any references from the past djob
+        */
+       BUG_ON(curr_djob);
+       curr_djob = job;
+       INIT_LIST_HEAD(&curr_djob->roi_cmd_list);
+
+       /* no ROI commands initially */
+       node->ncmds = 0;
+       INIT_LIST_HEAD(&node->node);
+       list_add_tail(&node->node, &curr_djob->roi_cmd_list);
+
+       /* register this djob with the djob cleaner
+        * initializes 'work' data struct
+        */
+       INIT_DELAYED_WORK(&curr_djob->cleaner, mdp_ppp_djob_cleaner);
+       INIT_LIST_HEAD(&curr_djob->entry);
+
+       curr_djob->p_src_file = 0;
+       curr_djob->p_dst_file = 0;
+
+       return job;
+}
+
+/* Undo the effect of mdp_ppp_new_djob() */
+inline void mdp_ppp_clear_curr_djob(void)
+{
+       if (likely(curr_djob)) {
+               mdp_ppp_del_djob(curr_djob);
+               curr_djob = NULL;
+       }
+}
+
+/* Cleanup dirty djobs */
+static void mdp_ppp_flush_dirty_djobs(void *cond)
+{
+       unsigned long flags;
+       struct mdp_ppp_djob *job;
+
+       /* Flush the jobs from the djob clnr queue */
+       while (cond && test_bit(0, (unsigned long *)cond)) {
+
+               /* Until we are done with the cleanup queue */
+               spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags);
+               if (list_empty(&mdp_ppp_djob_clnrq)) {
+                       spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
+                       break;
+               }
+
+               MDP_PPP_DEBUG_MSG("flushing djobs ... loop \n");
+
+               /* Retrieve the job that needs to be cleaned */
+               job = list_entry(mdp_ppp_djob_clnrq.next,
+                               struct mdp_ppp_djob, entry);
+               list_del_init(&job->entry);
+               spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
+
+               /* Keep mem state coherent */
+               msm_fb_ensure_mem_coherency_after_dma(job->info, &job->req, 1);
+
+               /* Schedule jobs for cleanup
+                * A seperate worker thread does this */
+               queue_delayed_work(mdp_ppp_djob_clnr, &job->cleaner,
+                       mdp_timer_duration);
+       }
+}
+
+/* If MDP PPP engine is busy, wait until it is available again */
+void mdp_ppp_wait(void)
+{
+       unsigned long flags;
+       int cond = 1;
+
+       /* keep flushing dirty djobs as long as MDP PPP engine is busy */
+       mdp_ppp_flush_dirty_djobs(&mdp_ppp_busy_flag);
+
+       /* block if MDP PPP engine is still busy */
+       spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+       if (test_bit(0, (unsigned long *)&mdp_ppp_busy_flag)) {
+
+               /* prepare for the wakeup event */
+               test_and_set_bit(0, (unsigned long *)&mdp_ppp_waiting);
+               INIT_COMPLETION(mdp_ppp_comp);
+               spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+               /* block uninterruptibly until available */
+               MDP_PPP_DEBUG_MSG("waiting for mdp... \n");
+               wait_for_completion_killable(&mdp_ppp_comp);
+
+               /* if MDP PPP engine is still free,
+                * disable INT_MDP if enabled
+                */
+               spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+               if (!test_bit(0, (unsigned long *)&mdp_ppp_busy_flag) &&
+               test_and_clear_bit(0, (unsigned long *)&mdp_ppp_intr_flag))
+                       mdp_disable_irq(MDP_PPP_TERM);
+       }
+       spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+       /* flush remaining dirty djobs, if any */
+       mdp_ppp_flush_dirty_djobs(&cond);
+}
+
+/* Program MDP PPP block to process this ROI */
+static void mdp_ppp_process_roi(struct list_head *roi_cmd_list)
+{
+
+       /* program PPP engine with registered ROI commands */
+       struct mdp_ppp_roi_cmd_set *node;
+       list_for_each_entry(node, roi_cmd_list, node) {
+               int i = 0;
+               for (; i < node->ncmds; i++) {
+                       MDP_PPP_DEBUG_MSG("%d: reg: 0x%x val: 0x%x \n",
+                                       i, node->cmd[i].reg, node->cmd[i].val);
+                       outpdw(node->cmd[i].reg, node->cmd[i].val);
+               }
+       }
+
+       /* kickoff MDP PPP engine */
+       MDP_PPP_DEBUG_MSG("kicking off mdp \n");
+       outpdw(MDP_BASE + 0x30, 0x1000);
+}
+
+/* Submit this display job to MDP PPP engine */
+static void mdp_ppp_dispatch_djob(struct mdp_ppp_djob *job)
+{
+       /* enable INT_MDP if disabled */
+       if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_intr_flag))
+               mdp_enable_irq(MDP_PPP_TERM);
+
+       /* turn on PPP and CMD blocks */
+       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+       mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+       /* process this ROI */
+       mdp_ppp_process_roi(&job->roi_cmd_list);
+}
+
+/* Enqueue this display job to be cleaned up later in "mdp_ppp_djob_done" */
+static inline void mdp_ppp_enqueue_djob(struct mdp_ppp_djob *job)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+       list_add_tail(&job->entry, &mdp_ppp_dq);
+       spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+}
+
+/* First enqueue display job for cleanup and dispatch immediately
+ * if MDP PPP engine is free */
+void mdp_ppp_process_curr_djob(void)
+{
+       /* enqueue djob */
+       mdp_ppp_enqueue_djob(curr_djob);
+
+       /* dispatch now if MDP PPP engine is free */
+       if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_busy_flag))
+               mdp_ppp_dispatch_djob(curr_djob);
+
+       /* done with the current djob */
+       curr_djob = NULL;
+}
+
+/* Called from mdp_isr - cleanup finished job and start with next
+ * if available else set MDP PPP engine free */
+void mdp_ppp_djob_done(void)
+{
+       struct mdp_ppp_djob *curr, *next;
+       unsigned long flags;
+
+       /* dequeue current */
+       spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+       curr = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob, entry);
+       list_del_init(&curr->entry);
+       spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+       /* cleanup current - enqueue in the djob clnr queue */
+       spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags);
+       list_add_tail(&curr->entry, &mdp_ppp_djob_clnrq);
+       spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
+
+       /* grab next pending */
+       spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+       if (!list_empty(&mdp_ppp_dq)) {
+               next = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob,
+                       entry);
+               spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+               /* process next in the queue */
+               mdp_ppp_process_roi(&next->roi_cmd_list);
+       } else {
+               /* no pending display job */
+               spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+               /* turn off PPP and CMD blocks - "in_isr" is TRUE */
+               mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+               mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+
+               /* notify if waiting */
+               if (test_and_clear_bit(0, (unsigned long *)&mdp_ppp_waiting))
+                       complete(&mdp_ppp_comp);
+
+               /* set free */
+               test_and_clear_bit(0, (unsigned long *)&mdp_ppp_busy_flag);
+       }
+}
diff --git a/drivers/staging/msm/mdp_ppp_dq.h b/drivers/staging/msm/mdp_ppp_dq.h
new file mode 100644 (file)
index 0000000..03e4e9a
--- /dev/null
@@ -0,0 +1,86 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDP_PPP_DQ_H
+#define MDP_PPP_DQ_H
+
+#include "msm_fb_def.h"
+
+#define MDP_PPP_DEBUG_MSG MSM_FB_DEBUG
+
+/* The maximum number of <Reg,Val> pairs in an mdp_ppp_roi_cmd_set structure (a
+ * node)
+ */
+#define MDP_PPP_ROI_NODE_SIZE 32
+
+/* ROI config command (<Reg,Val> pair) for MDP PPP block */
+struct mdp_ppp_roi_cmd {
+       uint32_t reg;
+       uint32_t val;
+};
+
+/* ROI config commands for MDP PPP block are stored in a list of
+ * mdp_ppp_roi_cmd_set structures (nodes).
+ */
+struct mdp_ppp_roi_cmd_set {
+       struct list_head node;
+       uint32_t ncmds; /* number of commands in this set (node). */
+       struct mdp_ppp_roi_cmd cmd[MDP_PPP_ROI_NODE_SIZE];
+};
+
+/* MDP PPP Display Job (DJob) */
+struct mdp_ppp_djob {
+       struct list_head entry;
+       /* One ROI per MDP PPP DJob */
+       struct list_head roi_cmd_list;
+       struct mdp_blit_req req;
+       struct fb_info *info;
+       struct delayed_work cleaner;
+       struct file *p_src_file, *p_dst_file;
+};
+
+extern struct completion mdp_ppp_comp;
+extern boolean mdp_ppp_waiting;
+extern unsigned long mdp_timer_duration;
+
+unsigned int mdp_ppp_async_op_get(void);
+void mdp_ppp_async_op_set(unsigned int flag);
+void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info,
+       struct mdp_blit_req *req_list, int req_list_count);
+void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file);
+void mdp_ppp_dq_init(void);
+void mdp_ppp_outdw(uint32_t addr, uint32_t data);
+struct mdp_ppp_djob *mdp_ppp_new_djob(void);
+void mdp_ppp_clear_curr_djob(void);
+void mdp_ppp_process_curr_djob(void);
+int mdp_ppp_get_ret_code(void);
+void mdp_ppp_djob_done(void);
+void mdp_ppp_wait(void);
+
+#endif /* MDP_PPP_DQ_H */
diff --git a/drivers/staging/msm/mdp_ppp_v20.c b/drivers/staging/msm/mdp_ppp_v20.c
new file mode 100644 (file)
index 0000000..b5b7271
--- /dev/null
@@ -0,0 +1,2486 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <asm/div64.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static MDP_SCALE_MODE mdp_curr_up_scale_xy;
+static MDP_SCALE_MODE mdp_curr_down_scale_x;
+static MDP_SCALE_MODE mdp_curr_down_scale_y;
+
+static long long mdp_do_div(long long num, long long den)
+{
+       do_div(num, den);
+       return num;
+}
+
+struct mdp_table_entry mdp_gaussian_blur_table[] = {
+       /* max variance */
+       { 0x5fffc, 0x20000080 },
+       { 0x50280, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50284, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50288, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x5028c, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50290, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50294, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50298, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x5029c, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502a0, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502a4, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502a8, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502ac, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502b0, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502b4, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502b8, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502bc, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502c0, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502c4, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502c8, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502cc, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502d0, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502d4, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502d8, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502dc, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502e0, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502e4, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502e8, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502ec, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502f0, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502f4, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502f8, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x502fc, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50300, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50304, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50308, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x5030c, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50310, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50314, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50318, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x5031c, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50320, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50324, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50328, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x5032c, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50330, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50334, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50338, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x5033c, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50340, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50344, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50348, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x5034c, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50350, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50354, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50358, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x5035c, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50360, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50364, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50368, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x5036c, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50370, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50374, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x50378, 0x20000080 },
+       { 0x5fffc, 0x20000080 },
+       { 0x5037c, 0x20000080 },
+};
+
+static void load_scale_table(
+       struct mdp_table_entry *table, int len)
+{
+       int i;
+       for (i = 0; i < len; i++)
+               MDP_OUTP(MDP_BASE + table[i].reg, table[i].val);
+}
+
+static void mdp_load_pr_upscale_table(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50204, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50208, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5020c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50210, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50214, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50218, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5021c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50220, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50224, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50228, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5022c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50230, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50234, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50238, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5023c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50240, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50244, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50248, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5024c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50250, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50254, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50258, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5025c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50260, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50264, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50268, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5026c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50270, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50274, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50278, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5027c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point2TOpoint4(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point2TOpoint4(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point4TOpoint6(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point4TOpoint6(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point6TOpoint8(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point6TOpoint8(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point8TO1(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point8TO1(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+       MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_bc_upscale_table(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+       MDP_OUTP(MDP_BASE + 0x50204, 0x7ec003f9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+       MDP_OUTP(MDP_BASE + 0x50208, 0x7d4003f3);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+       MDP_OUTP(MDP_BASE + 0x5020c, 0x7b8003ed);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+       MDP_OUTP(MDP_BASE + 0x50210, 0x794003e8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+       MDP_OUTP(MDP_BASE + 0x50214, 0x76c003e4);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+       MDP_OUTP(MDP_BASE + 0x50218, 0x73c003e0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+       MDP_OUTP(MDP_BASE + 0x5021c, 0x708003de);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+       MDP_OUTP(MDP_BASE + 0x50220, 0x6d0003db);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+       MDP_OUTP(MDP_BASE + 0x50224, 0x698003d9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+       MDP_OUTP(MDP_BASE + 0x50228, 0x654003d8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+       MDP_OUTP(MDP_BASE + 0x5022c, 0x610003d7);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+       MDP_OUTP(MDP_BASE + 0x50230, 0x5c8003d7);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+       MDP_OUTP(MDP_BASE + 0x50234, 0x580003d7);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+       MDP_OUTP(MDP_BASE + 0x50238, 0x534003d8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+       MDP_OUTP(MDP_BASE + 0x5023c, 0x4e8003d8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+       MDP_OUTP(MDP_BASE + 0x50240, 0x494003da);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+       MDP_OUTP(MDP_BASE + 0x50244, 0x448003db);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+       MDP_OUTP(MDP_BASE + 0x50248, 0x3f4003dd);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+       MDP_OUTP(MDP_BASE + 0x5024c, 0x3a4003df);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+       MDP_OUTP(MDP_BASE + 0x50250, 0x354003e1);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+       MDP_OUTP(MDP_BASE + 0x50254, 0x304003e3);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+       MDP_OUTP(MDP_BASE + 0x50258, 0x2b0003e6);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+       MDP_OUTP(MDP_BASE + 0x5025c, 0x260003e8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+       MDP_OUTP(MDP_BASE + 0x50260, 0x214003eb);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+       MDP_OUTP(MDP_BASE + 0x50264, 0x1c4003ee);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+       MDP_OUTP(MDP_BASE + 0x50268, 0x17c003f1);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+       MDP_OUTP(MDP_BASE + 0x5026c, 0x134003f3);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+       MDP_OUTP(MDP_BASE + 0x50270, 0xf0003f6);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+       MDP_OUTP(MDP_BASE + 0x50274, 0xac003f9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+       MDP_OUTP(MDP_BASE + 0x50278, 0x70003fb);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+       MDP_OUTP(MDP_BASE + 0x5027c, 0x34003fe);
+}
+
+static void mdp_load_bc_downscale_table_x_point2TOpoint4(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
+       MDP_OUTP(MDP_BASE + 0x50280, 0x23400083);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
+       MDP_OUTP(MDP_BASE + 0x50284, 0x23000083);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
+       MDP_OUTP(MDP_BASE + 0x50288, 0x23000082);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
+       MDP_OUTP(MDP_BASE + 0x5028c, 0x23000081);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
+       MDP_OUTP(MDP_BASE + 0x50290, 0x23000080);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
+       MDP_OUTP(MDP_BASE + 0x50294, 0x22c0007f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
+       MDP_OUTP(MDP_BASE + 0x50298, 0x2280007f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
+       MDP_OUTP(MDP_BASE + 0x5029c, 0x2280007e);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
+       MDP_OUTP(MDP_BASE + 0x502a0, 0x2280007d);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
+       MDP_OUTP(MDP_BASE + 0x502a4, 0x2240007d);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
+       MDP_OUTP(MDP_BASE + 0x502a8, 0x2240007c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
+       MDP_OUTP(MDP_BASE + 0x502ac, 0x2240007b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
+       MDP_OUTP(MDP_BASE + 0x502b0, 0x2200007b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
+       MDP_OUTP(MDP_BASE + 0x502b4, 0x22400079);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
+       MDP_OUTP(MDP_BASE + 0x502b8, 0x22400078);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
+       MDP_OUTP(MDP_BASE + 0x502bc, 0x22400077);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
+       MDP_OUTP(MDP_BASE + 0x502c0, 0x22000077);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
+       MDP_OUTP(MDP_BASE + 0x502c4, 0x22000076);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
+       MDP_OUTP(MDP_BASE + 0x502c8, 0x22000075);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
+       MDP_OUTP(MDP_BASE + 0x502cc, 0x21c00075);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
+       MDP_OUTP(MDP_BASE + 0x502d0, 0x21c00074);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
+       MDP_OUTP(MDP_BASE + 0x502d4, 0x21c00073);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
+       MDP_OUTP(MDP_BASE + 0x502d8, 0x21800073);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
+       MDP_OUTP(MDP_BASE + 0x502dc, 0x21800072);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
+       MDP_OUTP(MDP_BASE + 0x502e0, 0x21800071);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
+       MDP_OUTP(MDP_BASE + 0x502e4, 0x21800070);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
+       MDP_OUTP(MDP_BASE + 0x502e8, 0x2180006f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
+       MDP_OUTP(MDP_BASE + 0x502ec, 0x2140006e);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
+       MDP_OUTP(MDP_BASE + 0x502f0, 0x2140006d);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
+       MDP_OUTP(MDP_BASE + 0x502f4, 0x2100006d);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
+       MDP_OUTP(MDP_BASE + 0x502f8, 0x2100006c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
+       MDP_OUTP(MDP_BASE + 0x502fc, 0x2100006b);
+}
+
+static void mdp_load_bc_downscale_table_y_point2TOpoint4(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
+       MDP_OUTP(MDP_BASE + 0x50300, 0x23400083);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
+       MDP_OUTP(MDP_BASE + 0x50304, 0x23000083);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
+       MDP_OUTP(MDP_BASE + 0x50308, 0x23000082);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
+       MDP_OUTP(MDP_BASE + 0x5030c, 0x23000081);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
+       MDP_OUTP(MDP_BASE + 0x50310, 0x23000080);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
+       MDP_OUTP(MDP_BASE + 0x50314, 0x22c0007f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
+       MDP_OUTP(MDP_BASE + 0x50318, 0x2280007f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
+       MDP_OUTP(MDP_BASE + 0x5031c, 0x2280007e);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
+       MDP_OUTP(MDP_BASE + 0x50320, 0x2280007d);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
+       MDP_OUTP(MDP_BASE + 0x50324, 0x2240007d);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
+       MDP_OUTP(MDP_BASE + 0x50328, 0x2240007c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
+       MDP_OUTP(MDP_BASE + 0x5032c, 0x2240007b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
+       MDP_OUTP(MDP_BASE + 0x50330, 0x2200007b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
+       MDP_OUTP(MDP_BASE + 0x50334, 0x22400079);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
+       MDP_OUTP(MDP_BASE + 0x50338, 0x22400078);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
+       MDP_OUTP(MDP_BASE + 0x5033c, 0x22400077);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
+       MDP_OUTP(MDP_BASE + 0x50340, 0x22000077);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
+       MDP_OUTP(MDP_BASE + 0x50344, 0x22000076);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
+       MDP_OUTP(MDP_BASE + 0x50348, 0x22000075);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
+       MDP_OUTP(MDP_BASE + 0x5034c, 0x21c00075);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
+       MDP_OUTP(MDP_BASE + 0x50350, 0x21c00074);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
+       MDP_OUTP(MDP_BASE + 0x50354, 0x21c00073);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
+       MDP_OUTP(MDP_BASE + 0x50358, 0x21800073);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
+       MDP_OUTP(MDP_BASE + 0x5035c, 0x21800072);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
+       MDP_OUTP(MDP_BASE + 0x50360, 0x21800071);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
+       MDP_OUTP(MDP_BASE + 0x50364, 0x21800070);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
+       MDP_OUTP(MDP_BASE + 0x50368, 0x2180006f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
+       MDP_OUTP(MDP_BASE + 0x5036c, 0x2140006e);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
+       MDP_OUTP(MDP_BASE + 0x50370, 0x2140006d);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
+       MDP_OUTP(MDP_BASE + 0x50374, 0x2100006d);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
+       MDP_OUTP(MDP_BASE + 0x50378, 0x2100006c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
+       MDP_OUTP(MDP_BASE + 0x5037c, 0x2100006b);
+}
+
+static void mdp_load_bc_downscale_table_x_point4TOpoint6(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
+       MDP_OUTP(MDP_BASE + 0x50280, 0x33800088);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
+       MDP_OUTP(MDP_BASE + 0x50284, 0x33400084);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
+       MDP_OUTP(MDP_BASE + 0x50288, 0x33000080);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
+       MDP_OUTP(MDP_BASE + 0x5028c, 0x3300007b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
+       MDP_OUTP(MDP_BASE + 0x50290, 0x32400077);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
+       MDP_OUTP(MDP_BASE + 0x50294, 0x32000073);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
+       MDP_OUTP(MDP_BASE + 0x50298, 0x31c0006f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
+       MDP_OUTP(MDP_BASE + 0x5029c, 0x3140006b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
+       MDP_OUTP(MDP_BASE + 0x502a0, 0x31000067);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
+       MDP_OUTP(MDP_BASE + 0x502a4, 0x30800062);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
+       MDP_OUTP(MDP_BASE + 0x502a8, 0x2fc0005f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
+       MDP_OUTP(MDP_BASE + 0x502ac, 0x2fc0005b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
+       MDP_OUTP(MDP_BASE + 0x502b0, 0x2f400057);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
+       MDP_OUTP(MDP_BASE + 0x502b4, 0x2e400054);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
+       MDP_OUTP(MDP_BASE + 0x502b8, 0x2e000050);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
+       MDP_OUTP(MDP_BASE + 0x502bc, 0x2d80004c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
+       MDP_OUTP(MDP_BASE + 0x502c0, 0x2d000049);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
+       MDP_OUTP(MDP_BASE + 0x502c4, 0x2c800045);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
+       MDP_OUTP(MDP_BASE + 0x502c8, 0x2c000042);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
+       MDP_OUTP(MDP_BASE + 0x502cc, 0x2b40003e);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
+       MDP_OUTP(MDP_BASE + 0x502d0, 0x2a80003b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
+       MDP_OUTP(MDP_BASE + 0x502d4, 0x2a000039);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
+       MDP_OUTP(MDP_BASE + 0x502d8, 0x29400036);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
+       MDP_OUTP(MDP_BASE + 0x502dc, 0x28800032);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
+       MDP_OUTP(MDP_BASE + 0x502e0, 0x2800002f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
+       MDP_OUTP(MDP_BASE + 0x502e4, 0x2740002c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
+       MDP_OUTP(MDP_BASE + 0x502e8, 0x26c00029);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
+       MDP_OUTP(MDP_BASE + 0x502ec, 0x26000027);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
+       MDP_OUTP(MDP_BASE + 0x502f0, 0x25000024);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
+       MDP_OUTP(MDP_BASE + 0x502f4, 0x24800021);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
+       MDP_OUTP(MDP_BASE + 0x502f8, 0x23800020);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
+       MDP_OUTP(MDP_BASE + 0x502fc, 0x2300001d);
+}
+
+static void mdp_load_bc_downscale_table_y_point4TOpoint6(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
+       MDP_OUTP(MDP_BASE + 0x50300, 0x33800088);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
+       MDP_OUTP(MDP_BASE + 0x50304, 0x33400084);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
+       MDP_OUTP(MDP_BASE + 0x50308, 0x33000080);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
+       MDP_OUTP(MDP_BASE + 0x5030c, 0x3300007b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
+       MDP_OUTP(MDP_BASE + 0x50310, 0x32400077);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
+       MDP_OUTP(MDP_BASE + 0x50314, 0x32000073);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
+       MDP_OUTP(MDP_BASE + 0x50318, 0x31c0006f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
+       MDP_OUTP(MDP_BASE + 0x5031c, 0x3140006b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
+       MDP_OUTP(MDP_BASE + 0x50320, 0x31000067);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
+       MDP_OUTP(MDP_BASE + 0x50324, 0x30800062);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
+       MDP_OUTP(MDP_BASE + 0x50328, 0x2fc0005f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
+       MDP_OUTP(MDP_BASE + 0x5032c, 0x2fc0005b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
+       MDP_OUTP(MDP_BASE + 0x50330, 0x2f400057);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
+       MDP_OUTP(MDP_BASE + 0x50334, 0x2e400054);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
+       MDP_OUTP(MDP_BASE + 0x50338, 0x2e000050);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
+       MDP_OUTP(MDP_BASE + 0x5033c, 0x2d80004c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
+       MDP_OUTP(MDP_BASE + 0x50340, 0x2d000049);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
+       MDP_OUTP(MDP_BASE + 0x50344, 0x2c800045);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
+       MDP_OUTP(MDP_BASE + 0x50348, 0x2c000042);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
+       MDP_OUTP(MDP_BASE + 0x5034c, 0x2b40003e);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
+       MDP_OUTP(MDP_BASE + 0x50350, 0x2a80003b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
+       MDP_OUTP(MDP_BASE + 0x50354, 0x2a000039);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
+       MDP_OUTP(MDP_BASE + 0x50358, 0x29400036);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
+       MDP_OUTP(MDP_BASE + 0x5035c, 0x28800032);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
+       MDP_OUTP(MDP_BASE + 0x50360, 0x2800002f);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
+       MDP_OUTP(MDP_BASE + 0x50364, 0x2740002c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
+       MDP_OUTP(MDP_BASE + 0x50368, 0x26c00029);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
+       MDP_OUTP(MDP_BASE + 0x5036c, 0x26000027);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
+       MDP_OUTP(MDP_BASE + 0x50370, 0x25000024);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
+       MDP_OUTP(MDP_BASE + 0x50374, 0x24800021);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
+       MDP_OUTP(MDP_BASE + 0x50378, 0x23800020);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
+       MDP_OUTP(MDP_BASE + 0x5037c, 0x2300001d);
+}
+
+static void mdp_load_bc_downscale_table_x_point6TOpoint8(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
+       MDP_OUTP(MDP_BASE + 0x50280, 0x4bc00068);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
+       MDP_OUTP(MDP_BASE + 0x50284, 0x4bc00060);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
+       MDP_OUTP(MDP_BASE + 0x50288, 0x4b800059);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
+       MDP_OUTP(MDP_BASE + 0x5028c, 0x4b000052);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
+       MDP_OUTP(MDP_BASE + 0x50290, 0x4a80004b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
+       MDP_OUTP(MDP_BASE + 0x50294, 0x4a000044);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
+       MDP_OUTP(MDP_BASE + 0x50298, 0x4940003d);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
+       MDP_OUTP(MDP_BASE + 0x5029c, 0x48400037);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
+       MDP_OUTP(MDP_BASE + 0x502a0, 0x47800031);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
+       MDP_OUTP(MDP_BASE + 0x502a4, 0x4640002b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
+       MDP_OUTP(MDP_BASE + 0x502a8, 0x45000026);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
+       MDP_OUTP(MDP_BASE + 0x502ac, 0x43800021);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
+       MDP_OUTP(MDP_BASE + 0x502b0, 0x4240001c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
+       MDP_OUTP(MDP_BASE + 0x502b4, 0x40800018);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
+       MDP_OUTP(MDP_BASE + 0x502b8, 0x3f000014);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
+       MDP_OUTP(MDP_BASE + 0x502bc, 0x3d400010);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
+       MDP_OUTP(MDP_BASE + 0x502c0, 0x3b80000c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
+       MDP_OUTP(MDP_BASE + 0x502c4, 0x39800009);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
+       MDP_OUTP(MDP_BASE + 0x502c8, 0x37c00006);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
+       MDP_OUTP(MDP_BASE + 0x502cc, 0x35800004);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
+       MDP_OUTP(MDP_BASE + 0x502d0, 0x33800002);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
+       MDP_OUTP(MDP_BASE + 0x502d4, 0x31400000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
+       MDP_OUTP(MDP_BASE + 0x502d8, 0x2f4003fe);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
+       MDP_OUTP(MDP_BASE + 0x502dc, 0x2d0003fc);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
+       MDP_OUTP(MDP_BASE + 0x502e0, 0x2b0003fb);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
+       MDP_OUTP(MDP_BASE + 0x502e4, 0x28c003fa);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
+       MDP_OUTP(MDP_BASE + 0x502e8, 0x268003f9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
+       MDP_OUTP(MDP_BASE + 0x502ec, 0x244003f9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
+       MDP_OUTP(MDP_BASE + 0x502f0, 0x224003f8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
+       MDP_OUTP(MDP_BASE + 0x502f4, 0x200003f8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
+       MDP_OUTP(MDP_BASE + 0x502f8, 0x1e0003f8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
+       MDP_OUTP(MDP_BASE + 0x502fc, 0x1c0003f8);
+}
+
+static void mdp_load_bc_downscale_table_y_point6TOpoint8(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
+       MDP_OUTP(MDP_BASE + 0x50300, 0x4bc00068);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
+       MDP_OUTP(MDP_BASE + 0x50304, 0x4bc00060);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
+       MDP_OUTP(MDP_BASE + 0x50308, 0x4b800059);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
+       MDP_OUTP(MDP_BASE + 0x5030c, 0x4b000052);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
+       MDP_OUTP(MDP_BASE + 0x50310, 0x4a80004b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
+       MDP_OUTP(MDP_BASE + 0x50314, 0x4a000044);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
+       MDP_OUTP(MDP_BASE + 0x50318, 0x4940003d);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
+       MDP_OUTP(MDP_BASE + 0x5031c, 0x48400037);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
+       MDP_OUTP(MDP_BASE + 0x50320, 0x47800031);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
+       MDP_OUTP(MDP_BASE + 0x50324, 0x4640002b);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
+       MDP_OUTP(MDP_BASE + 0x50328, 0x45000026);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
+       MDP_OUTP(MDP_BASE + 0x5032c, 0x43800021);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
+       MDP_OUTP(MDP_BASE + 0x50330, 0x4240001c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
+       MDP_OUTP(MDP_BASE + 0x50334, 0x40800018);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
+       MDP_OUTP(MDP_BASE + 0x50338, 0x3f000014);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
+       MDP_OUTP(MDP_BASE + 0x5033c, 0x3d400010);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
+       MDP_OUTP(MDP_BASE + 0x50340, 0x3b80000c);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
+       MDP_OUTP(MDP_BASE + 0x50344, 0x39800009);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
+       MDP_OUTP(MDP_BASE + 0x50348, 0x37c00006);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
+       MDP_OUTP(MDP_BASE + 0x5034c, 0x35800004);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
+       MDP_OUTP(MDP_BASE + 0x50350, 0x33800002);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
+       MDP_OUTP(MDP_BASE + 0x50354, 0x31400000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
+       MDP_OUTP(MDP_BASE + 0x50358, 0x2f4003fe);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
+       MDP_OUTP(MDP_BASE + 0x5035c, 0x2d0003fc);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
+       MDP_OUTP(MDP_BASE + 0x50360, 0x2b0003fb);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
+       MDP_OUTP(MDP_BASE + 0x50364, 0x28c003fa);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
+       MDP_OUTP(MDP_BASE + 0x50368, 0x268003f9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
+       MDP_OUTP(MDP_BASE + 0x5036c, 0x244003f9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
+       MDP_OUTP(MDP_BASE + 0x50370, 0x224003f8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
+       MDP_OUTP(MDP_BASE + 0x50374, 0x200003f8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
+       MDP_OUTP(MDP_BASE + 0x50378, 0x1e0003f8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
+       MDP_OUTP(MDP_BASE + 0x5037c, 0x1c0003f8);
+}
+
+static void mdp_load_bc_downscale_table_x_point8TO1(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+       MDP_OUTP(MDP_BASE + 0x50284, 0x7ec003f9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+       MDP_OUTP(MDP_BASE + 0x50288, 0x7d4003f3);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+       MDP_OUTP(MDP_BASE + 0x5028c, 0x7b8003ed);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+       MDP_OUTP(MDP_BASE + 0x50290, 0x794003e8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+       MDP_OUTP(MDP_BASE + 0x50294, 0x76c003e4);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+       MDP_OUTP(MDP_BASE + 0x50298, 0x73c003e0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+       MDP_OUTP(MDP_BASE + 0x5029c, 0x708003de);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+       MDP_OUTP(MDP_BASE + 0x502a0, 0x6d0003db);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+       MDP_OUTP(MDP_BASE + 0x502a4, 0x698003d9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+       MDP_OUTP(MDP_BASE + 0x502a8, 0x654003d8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+       MDP_OUTP(MDP_BASE + 0x502ac, 0x610003d7);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+       MDP_OUTP(MDP_BASE + 0x502b0, 0x5c8003d7);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+       MDP_OUTP(MDP_BASE + 0x502b4, 0x580003d7);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+       MDP_OUTP(MDP_BASE + 0x502b8, 0x534003d8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+       MDP_OUTP(MDP_BASE + 0x502bc, 0x4e8003d8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+       MDP_OUTP(MDP_BASE + 0x502c0, 0x494003da);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+       MDP_OUTP(MDP_BASE + 0x502c4, 0x448003db);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+       MDP_OUTP(MDP_BASE + 0x502c8, 0x3f4003dd);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+       MDP_OUTP(MDP_BASE + 0x502cc, 0x3a4003df);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+       MDP_OUTP(MDP_BASE + 0x502d0, 0x354003e1);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+       MDP_OUTP(MDP_BASE + 0x502d4, 0x304003e3);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+       MDP_OUTP(MDP_BASE + 0x502d8, 0x2b0003e6);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+       MDP_OUTP(MDP_BASE + 0x502dc, 0x260003e8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+       MDP_OUTP(MDP_BASE + 0x502e0, 0x214003eb);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+       MDP_OUTP(MDP_BASE + 0x502e4, 0x1c4003ee);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+       MDP_OUTP(MDP_BASE + 0x502e8, 0x17c003f1);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+       MDP_OUTP(MDP_BASE + 0x502ec, 0x134003f3);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+       MDP_OUTP(MDP_BASE + 0x502f0, 0xf0003f6);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+       MDP_OUTP(MDP_BASE + 0x502f4, 0xac003f9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+       MDP_OUTP(MDP_BASE + 0x502f8, 0x70003fb);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+       MDP_OUTP(MDP_BASE + 0x502fc, 0x34003fe);
+}
+
+static void mdp_load_bc_downscale_table_y_point8TO1(void)
+{
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+       MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+       MDP_OUTP(MDP_BASE + 0x50304, 0x7ec003f9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+       MDP_OUTP(MDP_BASE + 0x50308, 0x7d4003f3);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+       MDP_OUTP(MDP_BASE + 0x5030c, 0x7b8003ed);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+       MDP_OUTP(MDP_BASE + 0x50310, 0x794003e8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+       MDP_OUTP(MDP_BASE + 0x50314, 0x76c003e4);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+       MDP_OUTP(MDP_BASE + 0x50318, 0x73c003e0);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+       MDP_OUTP(MDP_BASE + 0x5031c, 0x708003de);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+       MDP_OUTP(MDP_BASE + 0x50320, 0x6d0003db);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+       MDP_OUTP(MDP_BASE + 0x50324, 0x698003d9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+       MDP_OUTP(MDP_BASE + 0x50328, 0x654003d8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+       MDP_OUTP(MDP_BASE + 0x5032c, 0x610003d7);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+       MDP_OUTP(MDP_BASE + 0x50330, 0x5c8003d7);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+       MDP_OUTP(MDP_BASE + 0x50334, 0x580003d7);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+       MDP_OUTP(MDP_BASE + 0x50338, 0x534003d8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+       MDP_OUTP(MDP_BASE + 0x5033c, 0x4e8003d8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+       MDP_OUTP(MDP_BASE + 0x50340, 0x494003da);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+       MDP_OUTP(MDP_BASE + 0x50344, 0x448003db);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+       MDP_OUTP(MDP_BASE + 0x50348, 0x3f4003dd);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+       MDP_OUTP(MDP_BASE + 0x5034c, 0x3a4003df);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+       MDP_OUTP(MDP_BASE + 0x50350, 0x354003e1);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+       MDP_OUTP(MDP_BASE + 0x50354, 0x304003e3);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+       MDP_OUTP(MDP_BASE + 0x50358, 0x2b0003e6);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+       MDP_OUTP(MDP_BASE + 0x5035c, 0x260003e8);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+       MDP_OUTP(MDP_BASE + 0x50360, 0x214003eb);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+       MDP_OUTP(MDP_BASE + 0x50364, 0x1c4003ee);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+       MDP_OUTP(MDP_BASE + 0x50368, 0x17c003f1);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+       MDP_OUTP(MDP_BASE + 0x5036c, 0x134003f3);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+       MDP_OUTP(MDP_BASE + 0x50370, 0xf0003f6);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+       MDP_OUTP(MDP_BASE + 0x50374, 0xac003f9);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+       MDP_OUTP(MDP_BASE + 0x50378, 0x70003fb);
+       MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+       MDP_OUTP(MDP_BASE + 0x5037c, 0x34003fe);
+}
+
+static int mdp_get_edge_cond(MDPIBUF *iBuf, uint32 *dup, uint32 *dup2)
+{
+       uint32 reg;
+       uint32 dst_roi_width;   /* Dimensions of DST ROI. */
+       uint32 dst_roi_height;  /* Used to calculate scaling ratios. */
+
+       /*
+        * positions of the luma pixel(relative to the image ) required for
+        * scaling the ROI
+        */
+       int32 luma_interp_point_left = 0; /* left-most luma pixel needed */
+       int32 luma_interp_point_right = 0; /* right-most luma pixel needed */
+       int32 luma_interp_point_top = 0; /* top-most luma pixel needed */
+       int32 luma_interp_point_bottom = 0; /* bottom-most luma pixel needed */
+
+       /*
+        * positions of the chroma pixel(relative to the image ) required for
+        * interpolating a chroma value at all required luma positions
+        */
+       /* left-most chroma pixel needed */
+       int32 chroma_interp_point_left = 0;
+       /* right-most chroma pixel needed */
+       int32 chroma_interp_point_right = 0;
+       /* top-most chroma pixel needed */
+       int32 chroma_interp_point_top = 0;
+       /* bottom-most chroma pixel needed */
+       int32 chroma_interp_point_bottom = 0;
+
+       /*
+        * a rectangular region within the chroma plane of the "image".
+        * Chroma pixels falling inside of this rectangle belongs to the ROI
+        */
+       int32 chroma_bound_left = 0;
+       int32 chroma_bound_right = 0;
+       int32 chroma_bound_top = 0;
+       int32 chroma_bound_bottom = 0;
+
+       /*
+        * number of chroma pixels to replicate on the left, right,
+        * top and bottom edge of the ROI.
+        */
+       int32 chroma_repeat_left = 0;
+       int32 chroma_repeat_right = 0;
+       int32 chroma_repeat_top = 0;
+       int32 chroma_repeat_bottom = 0;
+
+       /*
+        * number of luma pixels to replicate on the left, right,
+        * top and bottom edge of the ROI.
+        */
+       int32 luma_repeat_left = 0;
+       int32 luma_repeat_right = 0;
+       int32 luma_repeat_top = 0;
+       int32 luma_repeat_bottom = 0;
+
+       boolean chroma_edge_enable;
+
+       uint32 _is_scale_enabled = 0;
+       uint32 _is_yuv_offsite_vertical = 0;
+
+       /* fg edge duplicate */
+       reg = 0x0;
+
+       if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {        /* if scaling enabled */
+
+               _is_scale_enabled = 1;
+
+               /*
+                * if rotation mode involves a 90 deg rotation, flip
+                * dst_roi_width with dst_roi_height.
+                * Scaling ratios is based on source ROI dimensions, and
+                * dst ROI dimensions before rotation.
+                */
+               if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+                       dst_roi_width = iBuf->roi.dst_height;
+                       dst_roi_height = iBuf->roi.dst_width;
+               } else {
+                       dst_roi_width = iBuf->roi.dst_width;
+                       dst_roi_height = iBuf->roi.dst_height;
+               }
+
+               /*
+                * Find out the luma pixels needed for scaling in the
+                * x direction (LEFT and RIGHT).  Locations of pixels are
+                * relative to the ROI. Upper-left corner of ROI corresponds
+                * to coordinates (0,0). Also set the number of luma pixel
+                * to repeat.
+                */
+               if (iBuf->roi.width > 3 * dst_roi_width) {
+                       /* scale factor < 1/3 */
+                       luma_interp_point_left = 0;
+                       luma_interp_point_right = (iBuf->roi.width - 1);
+                       luma_repeat_left = 0;
+                       luma_repeat_right = 0;
+               } else if (iBuf->roi.width == 3 * dst_roi_width) {
+                       /* scale factor == 1/3 */
+                       luma_interp_point_left = 0;
+                       luma_interp_point_right = (iBuf->roi.width - 1) + 1;
+                       luma_repeat_left = 0;
+                       luma_repeat_right = 1;
+               } else if ((iBuf->roi.width > dst_roi_width) &&
+                          (iBuf->roi.width < 3 * dst_roi_width)) {
+                       /* 1/3 < scale factor < 1 */
+                       luma_interp_point_left = -1;
+                       luma_interp_point_right = (iBuf->roi.width - 1) + 1;
+                       luma_repeat_left = 1;
+                       luma_repeat_right = 1;
+               }
+
+               else if (iBuf->roi.width == dst_roi_width) {
+                       /* scale factor == 1 */
+                       luma_interp_point_left = -1;
+                       luma_interp_point_right = (iBuf->roi.width - 1) + 2;
+                       luma_repeat_left = 1;
+                       luma_repeat_right = 2;
+               } else {        /* (iBuf->roi.width < dst_roi_width) */
+                         /* scale factor > 1 */
+                       luma_interp_point_left = -2;
+                       luma_interp_point_right = (iBuf->roi.width - 1) + 2;
+                       luma_repeat_left = 2;
+                       luma_repeat_right = 2;
+               }
+
+               /*
+                * Find out the number of pixels needed for scaling in the
+                * y direction (TOP and BOTTOM).  Locations of pixels are
+                * relative to the ROI. Upper-left corner of ROI corresponds
+                * to coordinates (0,0). Also set the number of luma pixel
+                * to repeat.
+                */
+               if (iBuf->roi.height > 3 * dst_roi_height) {
+                       /* scale factor < 1/3 */
+                       luma_interp_point_top = 0;
+                       luma_interp_point_bottom = (iBuf->roi.height - 1);
+                       luma_repeat_top = 0;
+                       luma_repeat_bottom = 0;
+               } else if (iBuf->roi.height == 3 * dst_roi_height) {
+                       /* scale factor == 1/3 */
+                       luma_interp_point_top = 0;
+                       luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
+                       luma_repeat_top = 0;
+                       luma_repeat_bottom = 1;
+               } else if ((iBuf->roi.height > dst_roi_height) &&
+                          (iBuf->roi.height < 3 * dst_roi_height)) {
+                       /* 1/3 < scale factor < 1 */
+                       luma_interp_point_top = -1;
+                       luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
+                       luma_repeat_top = 1;
+                       luma_repeat_bottom = 1;
+               } else if (iBuf->roi.height == dst_roi_height) {
+                       /* scale factor == 1 */
+                       luma_interp_point_top = -1;
+                       luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
+                       luma_repeat_top = 1;
+                       luma_repeat_bottom = 2;
+               } else {        /* (iBuf->roi.height < dst_roi_height) */
+                        /* scale factor > 1 */
+                       luma_interp_point_top = -2;
+                       luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
+                       luma_repeat_top = 2;
+                       luma_repeat_bottom = 2;
+               }
+       }                       /* if (iBuf->scale.scale_flag) */
+       else {                  /* scaling disabled */
+               /*
+                * Since no scaling needed, Tile Fetch does not require any
+                * more luma pixel than what the ROI contains.
+                */
+               luma_interp_point_left = (int32) 0;
+               luma_interp_point_right = (int32) (iBuf->roi.width - 1);
+               luma_interp_point_top = (int32) 0;
+               luma_interp_point_bottom = (int32) (iBuf->roi.height - 1);
+
+               luma_repeat_left = 0;
+               luma_repeat_right = 0;
+               luma_repeat_top = 0;
+               luma_repeat_bottom = 0;
+       }
+
+       /* After adding the ROI offsets, we have locations of
+        * luma_interp_points relative to the image.
+        */
+       luma_interp_point_left += (int32) (iBuf->roi.x);
+       luma_interp_point_right += (int32) (iBuf->roi.x);
+       luma_interp_point_top += (int32) (iBuf->roi.y);
+       luma_interp_point_bottom += (int32) (iBuf->roi.y);
+
+       /*
+        * After adding the ROI offsets, we have locations of
+        * chroma_interp_points relative to the image.
+        */
+       chroma_interp_point_left = luma_interp_point_left;
+       chroma_interp_point_right = luma_interp_point_right;
+       chroma_interp_point_top = luma_interp_point_top;
+       chroma_interp_point_bottom = luma_interp_point_bottom;
+
+       chroma_edge_enable = TRUE;
+       /* find out which chroma pixels are needed for chroma upsampling. */
+       switch (iBuf->mdpImg.imgType) {
+               /*
+                * cosite in horizontal axis
+                * fully sampled in vertical axis
+                */
+       case MDP_Y_CBCR_H2V1:
+       case MDP_Y_CRCB_H2V1:
+       case MDP_YCRYCB_H2V1:
+               /* floor( luma_interp_point_left / 2 ); */
+               chroma_interp_point_left = luma_interp_point_left >> 1;
+               /* floor( ( luma_interp_point_right + 1 ) / 2 ); */
+               chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
+
+               chroma_interp_point_top = luma_interp_point_top;
+               chroma_interp_point_bottom = luma_interp_point_bottom;
+               break;
+
+               /*
+                * cosite in horizontal axis
+                * offsite in vertical axis
+                */
+       case MDP_Y_CBCR_H2V2:
+       case MDP_Y_CRCB_H2V2:
+               /* floor( luma_interp_point_left / 2) */
+               chroma_interp_point_left = luma_interp_point_left >> 1;
+
+               /* floor( ( luma_interp_point_right + 1 )/ 2 ) */
+               chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
+
+               /* floor( (luma_interp_point_top - 1 ) / 2 ) */
+               chroma_interp_point_top = (luma_interp_point_top - 1) >> 1;
+
+               /* floor( ( luma_interp_point_bottom + 1 ) / 2 ) */
+               chroma_interp_point_bottom =
+                   (luma_interp_point_bottom + 1) >> 1;
+
+               _is_yuv_offsite_vertical = 1;
+               break;
+
+       default:
+               chroma_edge_enable = FALSE;
+               chroma_interp_point_left = luma_interp_point_left;
+               chroma_interp_point_right = luma_interp_point_right;
+               chroma_interp_point_top = luma_interp_point_top;
+               chroma_interp_point_bottom = luma_interp_point_bottom;
+
+               break;
+       }
+
+       /* only if the image type is in YUV domain, we calculate chroma edge */
+       if (chroma_edge_enable) {
+               /* Defines which chroma pixels belongs to the roi */
+               switch (iBuf->mdpImg.imgType) {
+                       /*
+                        * Cosite in horizontal direction, and fully sampled
+                        * in vertical direction.
+                        */
+               case MDP_Y_CBCR_H2V1:
+               case MDP_Y_CRCB_H2V1:
+               case MDP_YCRYCB_H2V1:
+                       /*
+                        * width of chroma ROI is 1/2 of size of luma ROI
+                        * height of chroma ROI same as size of luma ROI
+                        */
+                       chroma_bound_left = iBuf->roi.x / 2;
+
+                       /* there are half as many chroma pixel as luma pixels */
+                       chroma_bound_right =
+                           (iBuf->roi.width + iBuf->roi.x - 1) / 2;
+                       chroma_bound_top = iBuf->roi.y;
+                       chroma_bound_bottom =
+                           (iBuf->roi.height + iBuf->roi.y - 1);
+                       break;
+
+               case MDP_Y_CBCR_H2V2:
+               case MDP_Y_CRCB_H2V2:
+                       /*
+                        * cosite in horizontal dir, and offsite in vertical dir
+                        * width of chroma ROI is 1/2 of size of luma ROI
+                        * height of chroma ROI is 1/2 of size of luma ROI
+                        */
+
+                       chroma_bound_left = iBuf->roi.x / 2;
+                       chroma_bound_right =
+                           (iBuf->roi.width + iBuf->roi.x - 1) / 2;
+                       chroma_bound_top = iBuf->roi.y / 2;
+                       chroma_bound_bottom =
+                           (iBuf->roi.height + iBuf->roi.y - 1) / 2;
+                       break;
+
+               default:
+                       /*
+                        * If no valid chroma sub-sampling format specified,
+                        * assume 4:4:4 ( i.e. fully sampled).  Set ROI
+                        * boundaries for chroma same as ROI boundaries for
+                        * luma.
+                        */
+                       chroma_bound_left = iBuf->roi.x;
+                       chroma_bound_right = iBuf->roi.width + iBuf->roi.x - 1;
+                       chroma_bound_top = iBuf->roi.y;
+                       chroma_bound_bottom =
+                           (iBuf->roi.height + iBuf->roi.y - 1);
+                       break;
+               }
+
+               /*
+                * Knowing which chroma pixels are needed, and which chroma
+                * pixels belong to the ROI (i.e. available for fetching ),
+                * calculate how many chroma pixels Tile Fetch needs to
+                * duplicate.  If any required chroma pixels falls outside
+                * of the ROI, Tile Fetch must obtain them by replicating
+                * pixels.
+                */
+               if (chroma_bound_left > chroma_interp_point_left)
+                       chroma_repeat_left =
+                           chroma_bound_left - chroma_interp_point_left;
+               else
+                       chroma_repeat_left = 0;
+
+               if (chroma_interp_point_right > chroma_bound_right)
+                       chroma_repeat_right =
+                           chroma_interp_point_right - chroma_bound_right;
+               else
+                       chroma_repeat_right = 0;
+
+               if (chroma_bound_top > chroma_interp_point_top)
+                       chroma_repeat_top =
+                           chroma_bound_top - chroma_interp_point_top;
+               else
+                       chroma_repeat_top = 0;
+
+               if (chroma_interp_point_bottom > chroma_bound_bottom)
+                       chroma_repeat_bottom =
+                           chroma_interp_point_bottom - chroma_bound_bottom;
+               else
+                       chroma_repeat_bottom = 0;
+
+               if (_is_scale_enabled && (iBuf->roi.height == 1)
+                   && _is_yuv_offsite_vertical) {
+                       chroma_repeat_bottom = 3;
+                       chroma_repeat_top = 0;
+               }
+       }
+       /* make sure chroma repeats are non-negative */
+       if ((chroma_repeat_left < 0) || (chroma_repeat_right < 0) ||
+           (chroma_repeat_top < 0) || (chroma_repeat_bottom < 0))
+               return -1;
+
+       /* make sure chroma repeats are no larger than 3 pixels */
+       if ((chroma_repeat_left > 3) || (chroma_repeat_right > 3) ||
+           (chroma_repeat_top > 3) || (chroma_repeat_bottom > 3))
+               return -1;
+
+       /* make sure luma repeats are non-negative */
+       if ((luma_repeat_left < 0) || (luma_repeat_right < 0) ||
+           (luma_repeat_top < 0) || (luma_repeat_bottom < 0))
+               return -1;
+
+       /* make sure luma repeats are no larger than 3 pixels */
+       if ((luma_repeat_left > 3) || (luma_repeat_right > 3) ||
+           (luma_repeat_top > 3) || (luma_repeat_bottom > 3))
+               return -1;
+
+       /* write chroma_repeat_left to register */
+       reg |= (chroma_repeat_left & 3) << MDP_LEFT_CHROMA;
+
+       /* write chroma_repeat_right to register */
+       reg |= (chroma_repeat_right & 3) << MDP_RIGHT_CHROMA;
+
+       /* write chroma_repeat_top to register */
+       reg |= (chroma_repeat_top & 3) << MDP_TOP_CHROMA;
+
+       /* write chroma_repeat_bottom to register */
+       reg |= (chroma_repeat_bottom & 3) << MDP_BOTTOM_CHROMA;
+
+       /* write luma_repeat_left to register */
+       reg |= (luma_repeat_left & 3) << MDP_LEFT_LUMA;
+
+       /* write luma_repeat_right to register */
+       reg |= (luma_repeat_right & 3) << MDP_RIGHT_LUMA;
+
+       /* write luma_repeat_top to register */
+       reg |= (luma_repeat_top & 3) << MDP_TOP_LUMA;
+
+       /* write luma_repeat_bottom to register */
+       reg |= (luma_repeat_bottom & 3) << MDP_BOTTOM_LUMA;
+
+       /* done with reg */
+       *dup = reg;
+
+       /* bg edge duplicate */
+       reg = 0x0;
+
+       switch (iBuf->ibuf_type) {
+       case MDP_Y_CBCR_H2V2:
+       case MDP_Y_CRCB_H2V2:
+               /*
+                * Edge condition for MDP_Y_CRCB/CBCR_H2V2 cosite only.
+                * For 420 cosite, 1 chroma replicated on all sides except
+                * left, so reg 101b8 should be 0x0209. For 420 offsite,
+                * 1 chroma replicated all sides.
+                */
+               if (iBuf->roi.lcd_y == 0) {
+                       reg |= BIT(MDP_TOP_CHROMA);
+               }
+
+               if ((iBuf->roi.lcd_y + iBuf->roi.dst_height) ==
+                   iBuf->ibuf_height) {
+                       reg |= BIT(MDP_BOTTOM_CHROMA);
+               }
+
+               if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
+                    iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
+                       reg |= BIT(MDP_RIGHT_CHROMA);
+               }
+
+               break;
+
+       case MDP_Y_CBCR_H2V1:
+       case MDP_Y_CRCB_H2V1:
+       case MDP_YCRYCB_H2V1:
+               if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
+                    iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
+                       reg |= BIT(MDP_RIGHT_CHROMA);
+               }
+               break;
+       default:
+               break;
+       }
+
+       *dup2 = reg;
+
+       return 0;
+}
+
+#define ADJUST_IP              /* for 1/3 scale factor fix */
+
+static int mdp_calc_scale_params(
+/* ROI origin coordinate for the dimension */
+                                       uint32 org,
+/* src ROI dimension */
+                                       uint32 dim_in,
+/* scaled ROI dimension*/
+                                       uint32 dim_out,
+/* is this ROI width dimension? */
+                                       boolean is_W,
+/* initial phase location address */
+                                       int32 *phase_init_ptr,
+/* phase increment location address */
+                                       uint32 *phase_step_ptr,
+/* ROI start over-fetch location address */
+                                       uint32 *num_repl_beg_ptr,
+/* ROI end over-fetch location address */
+                                       uint32 *num_repl_end_ptr)
+{
+       boolean rpa_on = FALSE;
+       int init_phase = 0;
+       uint32 beg_of = 0;
+       uint32 end_of = 0;
+       uint64 numer = 0;
+       uint64 denom = 0;
+       /*uint64 inverter = 1; */
+       int64 point5 = 1;
+       int64 one = 1;
+       int64 k1, k2, k3, k4;   /* linear equation coefficients */
+       uint64 int_mask;
+       uint64 fract_mask;
+       uint64 Os;
+       int64 Osprime;
+       int64 Od;
+       int64 Odprime;
+       int64 Oreq;
+       uint64 Es;
+       uint64 Ed;
+       uint64 Ereq;
+#ifdef ADJUST_IP
+       int64 IP64;
+       int64 delta;
+#endif
+       uint32 mult;
+
+       /*
+        * The phase accumulator should really be rational for all cases in a
+        * general purpose polyphase scaler for a tiled architecture with
+        * non-zero * origin capability because there is no way to represent
+        * certain scale factors in fixed point regardless of precision.
+        * The error incurred in attempting to use fixed point is most
+        * eggregious for SF where 1/SF is an integral multiple of 1/3.
+        *
+        * However, since the MDP2 has already been committed to HW, we
+        * only use the rational phase accumulator (RPA) when 1/SF is an
+        * integral multiple of 1/3.  This will help minimize regressions in
+        * matching the HW to the C-Sim.
+        */
+       /*
+        * Set the RPA flag for this dimension.
+        *
+        * In order for 1/SF (dim_in/dim_out) to be an integral multiple of
+        * 1/3, dim_out must be an integral multiple of 3.
+        */
+       if (!(dim_out % 3)) {
+               mult = dim_out / 3;
+               rpa_on = (!(dim_in % mult));
+       }
+
+       numer = dim_out;
+       denom = dim_in;
+
+       /*
+        * convert to U30.34 before division
+        *
+        * The K vectors carry 4 extra bits of precision
+        * and are rounded.
+        *
+        * We initially go 5 bits over then round by adding
+        * 1 and right shifting by 1
+        * so final result is U31.33
+        */
+       numer <<= PQF_PLUS_5;
+
+       /* now calculate the scale factor (aka k3) */
+       k3 = ((mdp_do_div(numer, denom) + 1) >> 1);
+
+       /* check scale factor for legal range [0.25 - 4.0] */
+       if (((k3 >> 4) < (1LL << PQF_MINUS_2)) ||
+           ((k3 >> 4) > (1LL << PQF_PLUS_2))) {
+               return -1;
+       }
+
+       /* calculate inverse scale factor (aka k1) for phase init */
+       numer = dim_in;
+       denom = dim_out;
+       numer <<= PQF_PLUS_5;
+       k1 = ((mdp_do_div(numer, denom) + 1) >> 1);
+
+       /*
+        * calculate initial phase and ROI overfetch
+        */
+       /* convert point5 & one to S39.24 (will always be positive) */
+       point5 <<= (PQF_PLUS_4 - 1);
+       one <<= PQF_PLUS_4;
+       k2 = ((k1 - one) >> 1);
+       init_phase = (int)(k2 >> 4);
+       k4 = ((k3 - one) >> 1);
+       if (k3 == one) {
+               /* the simple case; SF = 1.0 */
+               beg_of = 1;
+               end_of = 2;
+       } else {
+               /* calculate the masks */
+               fract_mask = one - 1;
+               int_mask = ~fract_mask;
+
+               if (!rpa_on) {
+                       /*
+                        * FIXED POINT IMPLEMENTATION
+                        */
+                       if (!org) {
+                               /* A fairly simple case; ROI origin = 0 */
+                               if (k1 < one) {
+                                       /* upscaling */
+                                       beg_of = end_of = 2;
+                               }
+                               /* 0.33 <= SF < 1.0 */
+                               else if (k1 < (3LL << PQF_PLUS_4))
+                                       beg_of = end_of = 1;
+                               /* 0.33 == SF */
+                               else if (k1 == (3LL << PQF_PLUS_4)) {
+                                       beg_of = 0;
+                                       end_of = 1;
+                               }
+                               /* 0.25 <= SF < 0.33 */
+                               else
+                                       beg_of = end_of = 0;
+                       } else {
+                               /*
+                                * The complicated case; ROI origin != 0
+                                * init_phase needs to be adjusted
+                                * OF is also position dependent
+                                */
+
+                               /* map (org - .5) into destination space */
+                               Os = ((uint64) org << 1) - 1;
+                               Od = ((k3 * Os) >> 1) + k4;
+
+                               /* take the ceiling */
+                               Odprime = (Od & int_mask);
+                               if (Odprime != Od)
+                                       Odprime += one;
+
+                               /* now map that back to source space */
+                               Osprime = (k1 * (Odprime >> PQF_PLUS_4)) + k2;
+
+                               /* then floor & decrement to calculate the required
+                                  starting coordinate */
+                               Oreq = (Osprime & int_mask) - one;
+
+                               /* calculate end coord in destination space then map to
+                                  source space */
+                               Ed = Odprime +
+                                   ((uint64) dim_out << PQF_PLUS_4) - one;
+                               Es = (k1 * (Ed >> PQF_PLUS_4)) + k2;
+
+                               /* now floor & increment by 2 to calculate the required
+                                  ending coordinate */
+                               Ereq = (Es & int_mask) + (one << 1);
+
+                               /* calculate initial phase */
+#ifdef ADJUST_IP
+
+                               IP64 = Osprime - Oreq;
+                               delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
+                               IP64 -= delta;
+
+                               /* limit to valid range before the left shift */
+                               delta = (IP64 & (1LL << 63)) ? 4 : -4;
+                               delta <<= PQF_PLUS_4;
+                               while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
+                                       IP64 += delta;
+
+                               /* right shift to account for extra bits of precision */
+                               init_phase = (int)(IP64 >> 4);
+
+#else /* ADJUST_IP */
+
+                               /* just calculate the real initial phase */
+                               init_phase = (int)((Osprime - Oreq) >> 4);
+
+#endif /* ADJUST_IP */
+
+                               /* calculate the overfetch */
+                               beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
+                               end_of =
+                                   (uint32) (Ereq >> PQF_PLUS_4) - (org +
+                                                                    dim_in -
+                                                                    1);
+                       }
+               } else {
+                       /*
+                        * RPA IMPLEMENTATION
+                        *
+                        * init_phase needs to be calculated in all RPA_on cases
+                        * because it's a numerator, not a fixed point value.
+                        */
+
+                       /* map (org - .5) into destination space */
+                       Os = ((uint64) org << PQF_PLUS_4) - point5;
+                       Od = mdp_do_div((dim_out * (Os + point5)),
+                                       dim_in) - point5;
+
+                       /* take the ceiling */
+                       Odprime = (Od & int_mask);
+                       if (Odprime != Od)
+                               Odprime += one;
+
+                       /* now map that back to source space */
+                       Osprime =
+                           mdp_do_div((dim_in * (Odprime + point5)),
+                                      dim_out) - point5;
+
+                       /* then floor & decrement to calculate the required
+                          starting coordinate */
+                       Oreq = (Osprime & int_mask) - one;
+
+                       /* calculate end coord in destination space then map to
+                          source space */
+                       Ed = Odprime + ((uint64) dim_out << PQF_PLUS_4) - one;
+                       Es = mdp_do_div((dim_in * (Ed + point5)),
+                                       dim_out) - point5;
+
+                       /* now floor & increment by 2 to calculate the required
+                          ending coordinate */
+                       Ereq = (Es & int_mask) + (one << 1);
+
+                       /* calculate initial phase */
+
+#ifdef ADJUST_IP
+
+                       IP64 = Osprime - Oreq;
+                       delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
+                       IP64 -= delta;
+
+                       /* limit to valid range before the left shift */
+                       delta = (IP64 & (1LL << 63)) ? 4 : -4;
+                       delta <<= PQF_PLUS_4;
+                       while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
+                               IP64 += delta;
+
+                       /* right shift to account for extra bits of precision */
+                       init_phase = (int)(IP64 >> 4);
+
+#else /* ADJUST_IP */
+
+                       /* just calculate the real initial phase */
+                       init_phase = (int)((Osprime - Oreq) >> 4);
+
+#endif /* ADJUST_IP */
+
+                       /* calculate the overfetch */
+                       beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
+                       end_of =
+                           (uint32) (Ereq >> PQF_PLUS_4) - (org + dim_in - 1);
+               }
+       }
+
+       /* return the scale parameters */
+       *phase_init_ptr = init_phase;
+       *phase_step_ptr = (uint32) (k1 >> 4);
+       *num_repl_beg_ptr = beg_of;
+       *num_repl_end_ptr = end_of;
+
+       return 0;
+}
+
+static uint8 *mdp_adjust_rot_addr(MDPIBUF *iBuf, uint8 *addr, uint32 uv)
+{
+       uint32 dest_ystride = iBuf->ibuf_width * iBuf->bpp;
+       uint32 h_slice = 1;
+
+       if (uv && ((iBuf->ibuf_type == MDP_Y_CBCR_H2V2) ||
+               (iBuf->ibuf_type == MDP_Y_CRCB_H2V2)))
+               h_slice = 2;
+
+       if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_ROT90) ^
+           MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_LR)) {
+               addr =
+                   addr + (iBuf->roi.dst_width -
+                           MIN(16, iBuf->roi.dst_width)) * iBuf->bpp;
+       }
+       if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_UD)) {
+               addr =
+                   addr + ((iBuf->roi.dst_height -
+                       MIN(16, iBuf->roi.dst_height))/h_slice) * dest_ystride;
+       }
+
+       return addr;
+}
+
+void mdp_set_scale(MDPIBUF *iBuf,
+                  uint32 dst_roi_width,
+                  uint32 dst_roi_height,
+                  boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
+{
+       uint32 dst_roi_width_scale;
+       uint32 dst_roi_height_scale;
+       boolean use_pr;
+       uint32 phasex_step = 0;
+       uint32 phasey_step = 0;
+       int32 phasex_init = 0;
+       int32 phasey_init = 0;
+       uint32 lines_dup = 0;
+       uint32 lines_dup_bg = 0;
+       uint32 dummy;
+       uint32 mdp_blur = 0;
+
+       if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
+               if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+                       dst_roi_width_scale = dst_roi_height;
+                       dst_roi_height_scale = dst_roi_width;
+               } else {
+                       dst_roi_width_scale = dst_roi_width;
+                       dst_roi_height_scale = dst_roi_height;
+               }
+
+               mdp_blur = iBuf->mdpImg.mdpOp & MDPOP_BLUR;
+
+               if ((dst_roi_width_scale != iBuf->roi.width) ||
+                   (dst_roi_height_scale != iBuf->roi.height) ||
+                       mdp_blur) {
+                       *pppop_reg_ptr |=
+                           (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+
+               /* let's use SHIM logic to calculate the partial ROI scaling */
+#if 0
+                       phasex_step =
+                           (uint32) mdp_do_div(0x20000000 * iBuf->roi.width,
+                                               dst_roi_width_scale);
+                       phasey_step =
+                           (uint32) mdp_do_div(0x20000000 * iBuf->roi.height,
+                                               dst_roi_height_scale);
+
+/*
+    phasex_step= ((long long) iBuf->roi.width * 0x20000000)/dst_roi_width_scale;
+    phasey_step= ((long long)iBuf->roi.height * 0x20000000)/dst_roi_height_scale;
+*/
+
+                       phasex_init =
+                           (((long long)phasex_step - 0x20000000) >> 1);
+                       phasey_init =
+                           (((long long)phasey_step - 0x20000000) >> 1);
+
+#else
+                       mdp_calc_scale_params(iBuf->roi.x, iBuf->roi.width,
+                                             dst_roi_width_scale, 1,
+                                             &phasex_init, &phasex_step,
+                                             &dummy, &dummy);
+                       mdp_calc_scale_params(iBuf->roi.y, iBuf->roi.height,
+                                             dst_roi_height_scale, 0,
+                                             &phasey_init, &phasey_step,
+                                             &dummy, &dummy);
+#endif
+                       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
+                                phasex_init);
+                       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
+                                phasey_init);
+                       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
+                                phasex_step);
+                       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
+                                phasey_step);
+
+                       use_pr = (inputRGB) && (outputRGB);
+
+                       if ((dst_roi_width_scale > iBuf->roi.width) ||
+                           (dst_roi_height_scale > iBuf->roi.height)) {
+                               if ((use_pr)
+                                   && (mdp_curr_up_scale_xy !=
+                                       MDP_PR_SCALE_UP)) {
+                                       mdp_load_pr_upscale_table();
+                                       mdp_curr_up_scale_xy = MDP_PR_SCALE_UP;
+                               } else if ((!use_pr)
+                                          && (mdp_curr_up_scale_xy !=
+                                              MDP_BC_SCALE_UP)) {
+                                       mdp_load_bc_upscale_table();
+                                       mdp_curr_up_scale_xy = MDP_BC_SCALE_UP;
+                               }
+                       }
+
+                       if (mdp_blur) {
+                               load_scale_table(mdp_gaussian_blur_table,
+                                       ARRAY_SIZE(mdp_gaussian_blur_table));
+                               mdp_curr_down_scale_x = MDP_SCALE_BLUR;
+                               mdp_curr_down_scale_y = MDP_SCALE_BLUR;
+                       }
+
+                       /* 0.2 < x <= 1 scaling factor */
+                       if ((dst_roi_width_scale <= iBuf->roi.width) &&
+                               !mdp_blur) {
+                               if (((dst_roi_width_scale * 10) /
+                                    iBuf->roi.width) > 8) {
+                                       if ((use_pr)
+                                           && (mdp_curr_down_scale_x !=
+                                               MDP_PR_SCALE_POINT8_1)) {
+                                               mdp_load_pr_downscale_table_x_point8TO1
+                                                   ();
+                                               mdp_curr_down_scale_x =
+                                                   MDP_PR_SCALE_POINT8_1;
+                                       } else if ((!use_pr)
+                                                  && (mdp_curr_down_scale_x !=
+                                                      MDP_BC_SCALE_POINT8_1)) {
+                                               mdp_load_bc_downscale_table_x_point8TO1
+                                                   ();
+                                               mdp_curr_down_scale_x =
+                                                   MDP_BC_SCALE_POINT8_1;
+                                       }
+                               } else
+                                   if (((dst_roi_width_scale * 10) /
+                                        iBuf->roi.width) > 6) {
+                                       if ((use_pr)
+                                           && (mdp_curr_down_scale_x !=
+                                               MDP_PR_SCALE_POINT6_POINT8)) {
+                                               mdp_load_pr_downscale_table_x_point6TOpoint8
+                                                   ();
+                                               mdp_curr_down_scale_x =
+                                                   MDP_PR_SCALE_POINT6_POINT8;
+                                       } else if ((!use_pr)
+                                                  && (mdp_curr_down_scale_x !=
+                                                      MDP_BC_SCALE_POINT6_POINT8))
+                                       {
+                                               mdp_load_bc_downscale_table_x_point6TOpoint8
+                                                   ();
+                                               mdp_curr_down_scale_x =
+                                                   MDP_BC_SCALE_POINT6_POINT8;
+                                       }
+                               } else
+                                   if (((dst_roi_width_scale * 10) /
+                                        iBuf->roi.width) > 4) {
+                                       if ((use_pr)
+                                           && (mdp_curr_down_scale_x !=
+                                               MDP_PR_SCALE_POINT4_POINT6)) {
+                                               mdp_load_pr_downscale_table_x_point4TOpoint6
+                                                   ();
+                                               mdp_curr_down_scale_x =
+                                                   MDP_PR_SCALE_POINT4_POINT6;
+                                       } else if ((!use_pr)
+                                                  && (mdp_curr_down_scale_x !=
+                                                      MDP_BC_SCALE_POINT4_POINT6))
+                                       {
+                                               mdp_load_bc_downscale_table_x_point4TOpoint6
+                                                   ();
+                                               mdp_curr_down_scale_x =
+                                                   MDP_BC_SCALE_POINT4_POINT6;
+                                       }
+                               } else {
+                                       if ((use_pr)
+                                           && (mdp_curr_down_scale_x !=
+                                               MDP_PR_SCALE_POINT2_POINT4)) {
+                                               mdp_load_pr_downscale_table_x_point2TOpoint4
+                                                   ();
+                                               mdp_curr_down_scale_x =
+                                                   MDP_PR_SCALE_POINT2_POINT4;
+                                       } else if ((!use_pr)
+                                                  && (mdp_curr_down_scale_x !=
+                                                      MDP_BC_SCALE_POINT2_POINT4))
+                                       {
+                                               mdp_load_bc_downscale_table_x_point2TOpoint4
+                                                   ();
+                                               mdp_curr_down_scale_x =
+                                                   MDP_BC_SCALE_POINT2_POINT4;
+                                       }
+                               }
+                       }
+                       /* 0.2 < y <= 1 scaling factor */
+                       if ((dst_roi_height_scale <= iBuf->roi.height) &&
+                               !mdp_blur) {
+                               if (((dst_roi_height_scale * 10) /
+                                    iBuf->roi.height) > 8) {
+                                       if ((use_pr)
+                                           && (mdp_curr_down_scale_y !=
+                                               MDP_PR_SCALE_POINT8_1)) {
+                                               mdp_load_pr_downscale_table_y_point8TO1
+                                                   ();
+                                               mdp_curr_down_scale_y =
+                                                   MDP_PR_SCALE_POINT8_1;
+                                       } else if ((!use_pr)
+                                                  && (mdp_curr_down_scale_y !=
+                                                      MDP_BC_SCALE_POINT8_1)) {
+                                               mdp_load_bc_downscale_table_y_point8TO1
+                                                   ();
+                                               mdp_curr_down_scale_y =
+                                                   MDP_BC_SCALE_POINT8_1;
+                                       }
+                               } else
+                                   if (((dst_roi_height_scale * 10) /
+                                        iBuf->roi.height) > 6) {
+                                       if ((use_pr)
+                                           && (mdp_curr_down_scale_y !=
+                                               MDP_PR_SCALE_POINT6_POINT8)) {
+                                               mdp_load_pr_downscale_table_y_point6TOpoint8
+                                                   ();
+                                               mdp_curr_down_scale_y =
+                                                   MDP_PR_SCALE_POINT6_POINT8;
+                                       } else if ((!use_pr)
+                                                  && (mdp_curr_down_scale_y !=
+                                                      MDP_BC_SCALE_POINT6_POINT8))
+                                       {
+                                               mdp_load_bc_downscale_table_y_point6TOpoint8
+                                                   ();
+                                               mdp_curr_down_scale_y =
+                                                   MDP_BC_SCALE_POINT6_POINT8;
+                                       }
+                               } else
+                                   if (((dst_roi_height_scale * 10) /
+                                        iBuf->roi.height) > 4) {
+                                       if ((use_pr)
+                                           && (mdp_curr_down_scale_y !=
+                                               MDP_PR_SCALE_POINT4_POINT6)) {
+                                               mdp_load_pr_downscale_table_y_point4TOpoint6
+                                                   ();
+                                               mdp_curr_down_scale_y =
+                                                   MDP_PR_SCALE_POINT4_POINT6;
+                                       } else if ((!use_pr)
+                                                  && (mdp_curr_down_scale_y !=
+                                                      MDP_BC_SCALE_POINT4_POINT6))
+                                       {
+                                               mdp_load_bc_downscale_table_y_point4TOpoint6
+                                                   ();
+                                               mdp_curr_down_scale_y =
+                                                   MDP_BC_SCALE_POINT4_POINT6;
+                                       }
+                               } else {
+                                       if ((use_pr)
+                                           && (mdp_curr_down_scale_y !=
+                                               MDP_PR_SCALE_POINT2_POINT4)) {
+                                               mdp_load_pr_downscale_table_y_point2TOpoint4
+                                                   ();
+                                               mdp_curr_down_scale_y =
+                                                   MDP_PR_SCALE_POINT2_POINT4;
+                                       } else if ((!use_pr)
+                                                  && (mdp_curr_down_scale_y !=
+                                                      MDP_BC_SCALE_POINT2_POINT4))
+                                       {
+                                               mdp_load_bc_downscale_table_y_point2TOpoint4
+                                                   ();
+                                               mdp_curr_down_scale_y =
+                                                   MDP_BC_SCALE_POINT2_POINT4;
+                                       }
+                               }
+                       }
+               } else {
+                       iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
+               }
+       }
+       /* setting edge condition here after scaling check */
+       if (mdp_get_edge_cond(iBuf, &lines_dup, &lines_dup_bg))
+               printk(KERN_ERR "msm_fb: mdp_get_edge_cond() error!\n");
+
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01b8, lines_dup);
+       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01bc, lines_dup_bg);
+}
+
+void mdp_init_scale_table(void)
+{
+       mdp_curr_up_scale_xy = MDP_INIT_SCALE;
+       mdp_curr_down_scale_x = MDP_INIT_SCALE;
+       mdp_curr_down_scale_y = MDP_INIT_SCALE;
+}
+
+void mdp_adjust_start_addr(uint8 **src0,
+                          uint8 **src1,
+                          int v_slice,
+                          int h_slice,
+                          int x,
+                          int y,
+                          uint32 width,
+                          uint32 height, int bpp, MDPIBUF *iBuf, int layer)
+{
+       *src0 += (x + y * width) * bpp;
+
+       /* if it's dest/bg buffer, we need to adjust it for rotation */
+       if (layer != 0)
+               *src0 = mdp_adjust_rot_addr(iBuf, *src0, 0);
+
+       if (*src1) {
+               /*
+                * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now
+                * we need to shift x direction same as y dir for offsite
+                */
+               *src1 +=
+                   ((x / h_slice) * h_slice +
+                    ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
+
+               /* if it's dest/bg buffer, we need to adjust it for rotation */
+               if (layer != 0)
+                       *src1 = mdp_adjust_rot_addr(iBuf, *src1, 1);
+       }
+}
+
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+                       uint32 *alpha,
+                       uint32 *tpVal,
+                       uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
+{
+       if (perPixelAlpha) {
+               *pppop_reg_ptr |= PPP_OP_ROT_ON |
+                   PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
+       } else {
+               if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+                   && (iBuf->mdpImg.alpha == 0xff)) {
+                       iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+               }
+
+               if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+                   && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+                       *pppop_reg_ptr |=
+                           PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+                           PPP_OP_BLEND_CONSTANT_ALPHA |
+                           PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+                           PPP_BLEND_CALPHA_TRNASP;
+
+                       *alpha = iBuf->mdpImg.alpha;
+                       *tpVal = iBuf->mdpImg.tpVal;
+               } else {
+                       if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
+                               *pppop_reg_ptr |= PPP_OP_ROT_ON |
+                                   PPP_OP_BLEND_ON |
+                                   PPP_OP_BLEND_SRCPIXEL_TRANSP;
+                               *tpVal = iBuf->mdpImg.tpVal;
+                       } else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) {
+                               *pppop_reg_ptr |= PPP_OP_ROT_ON |
+                                   PPP_OP_BLEND_ON |
+                                   PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+                                   PPP_OP_BLEND_CONSTANT_ALPHA;
+                               *alpha = iBuf->mdpImg.alpha;
+                       }
+               }
+       }
+}
diff --git a/drivers/staging/msm/mdp_ppp_v31.c b/drivers/staging/msm/mdp_ppp_v31.c
new file mode 100644 (file)
index 0000000..76495db
--- /dev/null
@@ -0,0 +1,828 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <asm/div64.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+#define MDP_SCALE_COEFF_NUM      32
+#define MDP_SCALE_0P2_TO_0P4_INDEX 0
+#define MDP_SCALE_0P4_TO_0P6_INDEX 32
+#define MDP_SCALE_0P6_TO_0P8_INDEX 64
+#define MDP_SCALE_0P8_TO_8P0_INDEX 96
+#define MDP_SCALE_COEFF_MASK 0x3ff
+
+#define MDP_SCALE_PR  0
+#define MDP_SCALE_FIR 1
+
+static uint32 mdp_scale_0p8_to_8p0_mode;
+static uint32 mdp_scale_0p6_to_0p8_mode;
+static uint32 mdp_scale_0p4_to_0p6_mode;
+static uint32 mdp_scale_0p2_to_0p4_mode;
+
+/* -------- All scaling range, "pixel repeat" -------- */
+static int16 mdp_scale_pixel_repeat_C0[MDP_SCALE_COEFF_NUM] = {
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int16 mdp_scale_pixel_repeat_C1[MDP_SCALE_COEFF_NUM] = {
+       511, 511, 511, 511, 511, 511, 511, 511,
+       511, 511, 511, 511, 511, 511, 511, 511,
+       511, 511, 511, 511, 511, 511, 511, 511,
+       511, 511, 511, 511, 511, 511, 511, 511
+};
+
+static int16 mdp_scale_pixel_repeat_C2[MDP_SCALE_COEFF_NUM] = {
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int16 mdp_scale_pixel_repeat_C3[MDP_SCALE_COEFF_NUM] = {
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* --------------------------- FIR ------------------------------------- */
+/* -------- Downscale, ranging from 0.8x to 8.0x of original size -------- */
+
+static int16 mdp_scale_0p8_to_8p0_C0[MDP_SCALE_COEFF_NUM] = {
+       0, -7, -13, -19, -24, -28, -32, -34, -37, -39,
+       -40, -41, -41, -41, -40, -40, -38, -37, -35, -33,
+       -31, -29, -26, -24, -21, -18, -15, -13, -10, -7,
+       -5, -2
+};
+
+static int16 mdp_scale_0p8_to_8p0_C1[MDP_SCALE_COEFF_NUM] = {
+       511, 507, 501, 494, 485, 475, 463, 450, 436, 422,
+       405, 388, 370, 352, 333, 314, 293, 274, 253, 233,
+       213, 193, 172, 152, 133, 113, 95, 77, 60, 43,
+       28, 13
+};
+
+static int16 mdp_scale_0p8_to_8p0_C2[MDP_SCALE_COEFF_NUM] = {
+       0, 13, 28, 43, 60, 77, 95, 113, 133, 152,
+       172, 193, 213, 233, 253, 274, 294, 314, 333, 352,
+       370, 388, 405, 422, 436, 450, 463, 475, 485, 494,
+       501, 507,
+};
+
+static int16 mdp_scale_0p8_to_8p0_C3[MDP_SCALE_COEFF_NUM] = {
+       0, -2, -5, -7, -10, -13, -15, -18, -21, -24,
+       -26, -29, -31, -33, -35, -37, -38, -40, -40, -41,
+       -41, -41, -40, -39, -37, -34, -32, -28, -24, -19,
+       -13, -7
+};
+
+/* -------- Downscale, ranging from 0.6x to 0.8x of original size -------- */
+
+static int16 mdp_scale_0p6_to_0p8_C0[MDP_SCALE_COEFF_NUM] = {
+       104, 96, 89, 82, 75, 68, 61, 55, 49, 43,
+       38, 33, 28, 24, 20, 16, 12, 9, 6, 4,
+       2, 0, -2, -4, -5, -6, -7, -7, -8, -8,
+       -8, -8
+};
+
+static int16 mdp_scale_0p6_to_0p8_C1[MDP_SCALE_COEFF_NUM] = {
+       303, 303, 302, 300, 298, 296, 293, 289, 286, 281,
+       276, 270, 265, 258, 252, 245, 238, 230, 223, 214,
+       206, 197, 189, 180, 172, 163, 154, 145, 137, 128,
+       120, 112
+};
+
+static int16 mdp_scale_0p6_to_0p8_C2[MDP_SCALE_COEFF_NUM] = {
+       112, 120, 128, 137, 145, 154, 163, 172, 180, 189,
+       197, 206, 214, 223, 230, 238, 245, 252, 258, 265,
+       270, 276, 281, 286, 289, 293, 296, 298, 300, 302,
+       303, 303
+};
+
+static int16 mdp_scale_0p6_to_0p8_C3[MDP_SCALE_COEFF_NUM] = {
+       -8, -8, -8, -8, -7, -7, -6, -5, -4, -2,
+       0, 2, 4, 6, 9, 12, 16, 20, 24, 28,
+       33, 38, 43, 49, 55, 61, 68, 75, 82, 89,
+       96, 104
+};
+
+/* -------- Downscale, ranging from 0.4x to 0.6x of original size -------- */
+
+static int16 mdp_scale_0p4_to_0p6_C0[MDP_SCALE_COEFF_NUM] = {
+       136, 132, 128, 123, 119, 115, 111, 107, 103, 98,
+       95, 91, 87, 84, 80, 76, 73, 69, 66, 62,
+       59, 57, 54, 50, 47, 44, 41, 39, 36, 33,
+       32, 29
+};
+
+static int16 mdp_scale_0p4_to_0p6_C1[MDP_SCALE_COEFF_NUM] = {
+       206, 205, 204, 204, 201, 200, 199, 197, 196, 194,
+       191, 191, 189, 185, 184, 182, 180, 178, 176, 173,
+       170, 168, 165, 162, 160, 157, 155, 152, 148, 146,
+       142, 140
+};
+
+static int16 mdp_scale_0p4_to_0p6_C2[MDP_SCALE_COEFF_NUM] = {
+       140, 142, 146, 148, 152, 155, 157, 160, 162, 165,
+       168, 170, 173, 176, 178, 180, 182, 184, 185, 189,
+       191, 191, 194, 196, 197, 199, 200, 201, 204, 204,
+       205, 206
+};
+
+static int16 mdp_scale_0p4_to_0p6_C3[MDP_SCALE_COEFF_NUM] = {
+       29, 32, 33, 36, 39, 41, 44, 47, 50, 54,
+       57, 59, 62, 66, 69, 73, 76, 80, 84, 87,
+       91, 95, 98, 103, 107, 111, 115, 119, 123, 128,
+       132, 136
+};
+
+/* -------- Downscale, ranging from 0.2x to 0.4x of original size -------- */
+
+static int16 mdp_scale_0p2_to_0p4_C0[MDP_SCALE_COEFF_NUM] = {
+       131, 131, 130, 129, 128, 127, 127, 126, 125, 125,
+       124, 123, 123, 121, 120, 119, 119, 118, 117, 117,
+       116, 115, 115, 114, 113, 112, 111, 110, 109, 109,
+       108, 107
+};
+
+static int16 mdp_scale_0p2_to_0p4_C1[MDP_SCALE_COEFF_NUM] = {
+       141, 140, 140, 140, 140, 139, 138, 138, 138, 137,
+       137, 137, 136, 137, 137, 137, 136, 136, 136, 135,
+       135, 135, 134, 134, 134, 134, 134, 133, 133, 132,
+       132, 132
+};
+
+static int16 mdp_scale_0p2_to_0p4_C2[MDP_SCALE_COEFF_NUM] = {
+       132, 132, 132, 133, 133, 134, 134, 134, 134, 134,
+       135, 135, 135, 136, 136, 136, 137, 137, 137, 136,
+       137, 137, 137, 138, 138, 138, 139, 140, 140, 140,
+       140, 141
+};
+
+static int16 mdp_scale_0p2_to_0p4_C3[MDP_SCALE_COEFF_NUM] = {
+       107, 108, 109, 109, 110, 111, 112, 113, 114, 115,
+       115, 116, 117, 117, 118, 119, 119, 120, 121, 123,
+       123, 124, 125, 125, 126, 127, 127, 128, 129, 130,
+       131, 131
+};
+
+static void mdp_update_scale_table(int index, int16 *c0, int16 *c1,
+                                  int16 *c2, int16 *c3)
+{
+       int i, val;
+
+       for (i = 0; i < MDP_SCALE_COEFF_NUM; i++) {
+               val =
+                   ((MDP_SCALE_COEFF_MASK & c1[i]) << 16) |
+                   (MDP_SCALE_COEFF_MASK & c0[i]);
+               MDP_OUTP(MDP_PPP_SCALE_COEFF_LSBn(index), val);
+               val =
+                   ((MDP_SCALE_COEFF_MASK & c3[i]) << 16) |
+                   (MDP_SCALE_COEFF_MASK & c2[i]);
+               MDP_OUTP(MDP_PPP_SCALE_COEFF_MSBn(index), val);
+               index++;
+       }
+}
+
+void mdp_init_scale_table(void)
+{
+       mdp_scale_0p2_to_0p4_mode = MDP_SCALE_FIR;
+       mdp_update_scale_table(MDP_SCALE_0P2_TO_0P4_INDEX,
+                              mdp_scale_0p2_to_0p4_C0,
+                              mdp_scale_0p2_to_0p4_C1,
+                              mdp_scale_0p2_to_0p4_C2,
+                              mdp_scale_0p2_to_0p4_C3);
+
+       mdp_scale_0p4_to_0p6_mode = MDP_SCALE_FIR;
+       mdp_update_scale_table(MDP_SCALE_0P4_TO_0P6_INDEX,
+                              mdp_scale_0p4_to_0p6_C0,
+                              mdp_scale_0p4_to_0p6_C1,
+                              mdp_scale_0p4_to_0p6_C2,
+                              mdp_scale_0p4_to_0p6_C3);
+
+       mdp_scale_0p6_to_0p8_mode = MDP_SCALE_FIR;
+       mdp_update_scale_table(MDP_SCALE_0P6_TO_0P8_INDEX,
+                              mdp_scale_0p6_to_0p8_C0,
+                              mdp_scale_0p6_to_0p8_C1,
+                              mdp_scale_0p6_to_0p8_C2,
+                              mdp_scale_0p6_to_0p8_C3);
+
+       mdp_scale_0p8_to_8p0_mode = MDP_SCALE_FIR;
+       mdp_update_scale_table(MDP_SCALE_0P8_TO_8P0_INDEX,
+                              mdp_scale_0p8_to_8p0_C0,
+                              mdp_scale_0p8_to_8p0_C1,
+                              mdp_scale_0p8_to_8p0_C2,
+                              mdp_scale_0p8_to_8p0_C3);
+}
+
+static long long mdp_do_div(long long num, long long den)
+{
+       do_div(num, den);
+       return num;
+}
+
+#define SCALER_PHASE_BITS 29
+#define HAL_MDP_PHASE_STEP_2P50    0x50000000
+#define HAL_MDP_PHASE_STEP_1P66    0x35555555
+#define HAL_MDP_PHASE_STEP_1P25    0x28000000
+
+struct phase_val {
+       int phase_init_x;
+       int phase_init_y;
+       int phase_step_x;
+       int phase_step_y;
+};
+
+static void mdp_calc_scaleInitPhase_3p1(uint32 in_w,
+                                       uint32 in_h,
+                                       uint32 out_w,
+                                       uint32 out_h,
+                                       boolean is_rotate,
+                                       boolean is_pp_x,
+                                       boolean is_pp_y, struct phase_val *pval)
+{
+       uint64 dst_ROI_width;
+       uint64 dst_ROI_height;
+       uint64 src_ROI_width;
+       uint64 src_ROI_height;
+
+       /*
+        * phase_step_x, phase_step_y, phase_init_x and phase_init_y
+        * are represented in fixed-point, unsigned 3.29 format
+        */
+       uint32 phase_step_x = 0;
+       uint32 phase_step_y = 0;
+       uint32 phase_init_x = 0;
+       uint32 phase_init_y = 0;
+       uint32 yscale_filter_sel, xscale_filter_sel;
+       uint32 scale_unit_sel_x, scale_unit_sel_y;
+
+       uint64 numerator, denominator;
+       uint64 temp_dim;
+
+       src_ROI_width = in_w;
+       src_ROI_height = in_h;
+       dst_ROI_width = out_w;
+       dst_ROI_height = out_h;
+
+       /* if there is a 90 degree rotation */
+       if (is_rotate) {
+               /* decide whether to use FIR or M/N for scaling */
+
+               /* if down-scaling by a factor smaller than 1/4 */
+               if (src_ROI_width > (4 * dst_ROI_height))
+                       scale_unit_sel_x = 1;   /* use M/N scalar */
+               else
+                       scale_unit_sel_x = 0;   /* use FIR scalar */
+
+               /* if down-scaling by a factor smaller than 1/4 */
+               if (src_ROI_height > (4 * dst_ROI_width))
+                       scale_unit_sel_y = 1;   /* use M/N scalar */
+               else
+                       scale_unit_sel_y = 0;   /* use FIR scalar */
+       } else {
+               /* decide whether to use FIR or M/N for scaling */
+
+               if (src_ROI_width > (4 * dst_ROI_width))
+                       scale_unit_sel_x = 1;   /* use M/N scalar */
+               else
+                       scale_unit_sel_x = 0;   /* use FIR scalar */
+
+               if (src_ROI_height > (4 * dst_ROI_height))
+                       scale_unit_sel_y = 1;   /* use M/N scalar */
+               else
+                       scale_unit_sel_y = 0;   /* use FIR scalar */
+
+       }
+
+       /* if there is a 90 degree rotation */
+       if (is_rotate) {
+               /* swap the width and height of dst ROI */
+               temp_dim = dst_ROI_width;
+               dst_ROI_width = dst_ROI_height;
+               dst_ROI_height = temp_dim;
+       }
+
+       /* calculate phase step for the x direction */
+
+       /* if destination is only 1 pixel wide, the value of phase_step_x
+          is unimportant. Assigning phase_step_x to src ROI width
+          as an arbitrary value. */
+       if (dst_ROI_width == 1)
+               phase_step_x = (uint32) ((src_ROI_width) << SCALER_PHASE_BITS);
+
+       /* if using FIR scalar */
+       else if (scale_unit_sel_x == 0) {
+
+               /* Calculate the quotient ( src_ROI_width - 1 ) / ( dst_ROI_width - 1)
+                  with u3.29 precision. Quotient is rounded up to the larger
+                  29th decimal point. */
+               numerator = (src_ROI_width - 1) << SCALER_PHASE_BITS;
+               denominator = (dst_ROI_width - 1);      /* never equals to 0 because of the "( dst_ROI_width == 1 ) case" */
+               phase_step_x = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* divide and round up to the larger 29th decimal point. */
+
+       }
+
+       /* if M/N scalar */
+       else if (scale_unit_sel_x == 1) {
+               /* Calculate the quotient ( src_ROI_width ) / ( dst_ROI_width)
+                  with u3.29 precision. Quotient is rounded down to the
+                  smaller 29th decimal point. */
+               numerator = (src_ROI_width) << SCALER_PHASE_BITS;
+               denominator = (dst_ROI_width);
+               phase_step_x = (uint32) mdp_do_div(numerator, denominator);
+       }
+       /* calculate phase step for the y direction */
+
+       /* if destination is only 1 pixel wide, the value of
+          phase_step_x is unimportant. Assigning phase_step_x
+          to src ROI width as an arbitrary value. */
+       if (dst_ROI_height == 1)
+               phase_step_y = (uint32) ((src_ROI_height) << SCALER_PHASE_BITS);
+
+       /* if FIR scalar */
+       else if (scale_unit_sel_y == 0) {
+               /* Calculate the quotient ( src_ROI_height - 1 ) / ( dst_ROI_height - 1)
+                  with u3.29 precision. Quotient is rounded up to the larger
+                  29th decimal point. */
+               numerator = (src_ROI_height - 1) << SCALER_PHASE_BITS;
+               denominator = (dst_ROI_height - 1);     /* never equals to 0 because of the "( dst_ROI_height == 1 )" case */
+               phase_step_y = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* Quotient is rounded up to the larger 29th decimal point. */
+
+       }
+
+       /* if M/N scalar */
+       else if (scale_unit_sel_y == 1) {
+               /* Calculate the quotient ( src_ROI_height ) / ( dst_ROI_height)
+                  with u3.29 precision. Quotient is rounded down to the smaller
+                  29th decimal point. */
+               numerator = (src_ROI_height) << SCALER_PHASE_BITS;
+               denominator = (dst_ROI_height);
+               phase_step_y = (uint32) mdp_do_div(numerator, denominator);
+       }
+
+       /* decide which set of FIR coefficients to use */
+       if (phase_step_x > HAL_MDP_PHASE_STEP_2P50)
+               xscale_filter_sel = 0;
+       else if (phase_step_x > HAL_MDP_PHASE_STEP_1P66)
+               xscale_filter_sel = 1;
+       else if (phase_step_x > HAL_MDP_PHASE_STEP_1P25)
+               xscale_filter_sel = 2;
+       else
+               xscale_filter_sel = 3;
+
+       if (phase_step_y > HAL_MDP_PHASE_STEP_2P50)
+               yscale_filter_sel = 0;
+       else if (phase_step_y > HAL_MDP_PHASE_STEP_1P66)
+               yscale_filter_sel = 1;
+       else if (phase_step_y > HAL_MDP_PHASE_STEP_1P25)
+               yscale_filter_sel = 2;
+       else
+               yscale_filter_sel = 3;
+
+       /* calculate phase init for the x direction */
+
+       /* if using FIR scalar */
+       if (scale_unit_sel_x == 0) {
+               if (dst_ROI_width == 1)
+                       phase_init_x =
+                           (uint32) ((src_ROI_width - 1) << SCALER_PHASE_BITS);
+               else
+                       phase_init_x = 0;
+
+       }
+       /* M over N scalar  */
+       else if (scale_unit_sel_x == 1)
+               phase_init_x = 0;
+
+       /* calculate phase init for the y direction
+          if using FIR scalar */
+       if (scale_unit_sel_y == 0) {
+               if (dst_ROI_height == 1)
+                       phase_init_y =
+                           (uint32) ((src_ROI_height -
+                                      1) << SCALER_PHASE_BITS);
+               else
+                       phase_init_y = 0;
+
+       }
+       /* M over N scalar   */
+       else if (scale_unit_sel_y == 1)
+               phase_init_y = 0;
+
+       /* write registers */
+       pval->phase_step_x = (uint32) phase_step_x;
+       pval->phase_step_y = (uint32) phase_step_y;
+       pval->phase_init_x = (uint32) phase_init_x;
+       pval->phase_init_y = (uint32) phase_init_y;
+
+       return;
+}
+
+void mdp_set_scale(MDPIBUF *iBuf,
+                  uint32 dst_roi_width,
+                  uint32 dst_roi_height,
+                  boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
+{
+       uint32 dst_roi_width_scale;
+       uint32 dst_roi_height_scale;
+       struct phase_val pval;
+       boolean use_pr;
+       uint32 ppp_scale_config = 0;
+
+       if (!inputRGB)
+               ppp_scale_config |= BIT(6);
+
+       if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
+               if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+                       dst_roi_width_scale = dst_roi_height;
+                       dst_roi_height_scale = dst_roi_width;
+               } else {
+                       dst_roi_width_scale = dst_roi_width;
+                       dst_roi_height_scale = dst_roi_height;
+               }
+
+               if ((dst_roi_width_scale != iBuf->roi.width) ||
+                   (dst_roi_height_scale != iBuf->roi.height) ||
+                       (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+                       *pppop_reg_ptr |=
+                           (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+
+                       mdp_calc_scaleInitPhase_3p1(iBuf->roi.width,
+                                                   iBuf->roi.height,
+                                                   dst_roi_width,
+                                                   dst_roi_height,
+                                                   iBuf->mdpImg.
+                                                   mdpOp & MDPOP_ROT90, 1, 1,
+                                                   &pval);
+
+                       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
+                                pval.phase_init_x);
+                       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
+                                pval.phase_init_y);
+                       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
+                                pval.phase_step_x);
+                       MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
+                                pval.phase_step_y);
+
+                       use_pr = (inputRGB) && (outputRGB);
+
+                       /* x-direction */
+                       if ((dst_roi_width_scale == iBuf->roi.width) &&
+                               !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+                               *pppop_reg_ptr &= ~PPP_OP_SCALE_X_ON;
+                       } else
+                           if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+                               8) {
+                               if ((use_pr)
+                                   && (mdp_scale_0p8_to_8p0_mode !=
+                                       MDP_SCALE_PR)) {
+                                       mdp_scale_0p8_to_8p0_mode =
+                                           MDP_SCALE_PR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P8_TO_8P0_INDEX,
+                                            mdp_scale_pixel_repeat_C0,
+                                            mdp_scale_pixel_repeat_C1,
+                                            mdp_scale_pixel_repeat_C2,
+                                            mdp_scale_pixel_repeat_C3);
+                               } else if ((!use_pr)
+                                          && (mdp_scale_0p8_to_8p0_mode !=
+                                              MDP_SCALE_FIR)) {
+                                       mdp_scale_0p8_to_8p0_mode =
+                                           MDP_SCALE_FIR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P8_TO_8P0_INDEX,
+                                            mdp_scale_0p8_to_8p0_C0,
+                                            mdp_scale_0p8_to_8p0_C1,
+                                            mdp_scale_0p8_to_8p0_C2,
+                                            mdp_scale_0p8_to_8p0_C3);
+                               }
+                               ppp_scale_config |= (SCALE_U1_SET << 2);
+                       } else
+                           if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+                               6) {
+                               if ((use_pr)
+                                   && (mdp_scale_0p6_to_0p8_mode !=
+                                       MDP_SCALE_PR)) {
+                                       mdp_scale_0p6_to_0p8_mode =
+                                           MDP_SCALE_PR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P6_TO_0P8_INDEX,
+                                            mdp_scale_pixel_repeat_C0,
+                                            mdp_scale_pixel_repeat_C1,
+                                            mdp_scale_pixel_repeat_C2,
+                                            mdp_scale_pixel_repeat_C3);
+                               } else if ((!use_pr)
+                                          && (mdp_scale_0p6_to_0p8_mode !=
+                                              MDP_SCALE_FIR)) {
+                                       mdp_scale_0p6_to_0p8_mode =
+                                           MDP_SCALE_FIR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P6_TO_0P8_INDEX,
+                                            mdp_scale_0p6_to_0p8_C0,
+                                            mdp_scale_0p6_to_0p8_C1,
+                                            mdp_scale_0p6_to_0p8_C2,
+                                            mdp_scale_0p6_to_0p8_C3);
+                               }
+                               ppp_scale_config |= (SCALE_D2_SET << 2);
+                       } else
+                           if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+                               4) {
+                               if ((use_pr)
+                                   && (mdp_scale_0p4_to_0p6_mode !=
+                                       MDP_SCALE_PR)) {
+                                       mdp_scale_0p4_to_0p6_mode =
+                                           MDP_SCALE_PR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P4_TO_0P6_INDEX,
+                                            mdp_scale_pixel_repeat_C0,
+                                            mdp_scale_pixel_repeat_C1,
+                                            mdp_scale_pixel_repeat_C2,
+                                            mdp_scale_pixel_repeat_C3);
+                               } else if ((!use_pr)
+                                          && (mdp_scale_0p4_to_0p6_mode !=
+                                              MDP_SCALE_FIR)) {
+                                       mdp_scale_0p4_to_0p6_mode =
+                                           MDP_SCALE_FIR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P4_TO_0P6_INDEX,
+                                            mdp_scale_0p4_to_0p6_C0,
+                                            mdp_scale_0p4_to_0p6_C1,
+                                            mdp_scale_0p4_to_0p6_C2,
+                                            mdp_scale_0p4_to_0p6_C3);
+                               }
+                               ppp_scale_config |= (SCALE_D1_SET << 2);
+                       } else
+                           if (((dst_roi_width_scale * 4) / iBuf->roi.width) >=
+                               1) {
+                               if ((use_pr)
+                                   && (mdp_scale_0p2_to_0p4_mode !=
+                                       MDP_SCALE_PR)) {
+                                       mdp_scale_0p2_to_0p4_mode =
+                                           MDP_SCALE_PR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P2_TO_0P4_INDEX,
+                                            mdp_scale_pixel_repeat_C0,
+                                            mdp_scale_pixel_repeat_C1,
+                                            mdp_scale_pixel_repeat_C2,
+                                            mdp_scale_pixel_repeat_C3);
+                               } else if ((!use_pr)
+                                          && (mdp_scale_0p2_to_0p4_mode !=
+                                              MDP_SCALE_FIR)) {
+                                       mdp_scale_0p2_to_0p4_mode =
+                                           MDP_SCALE_FIR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P2_TO_0P4_INDEX,
+                                            mdp_scale_0p2_to_0p4_C0,
+                                            mdp_scale_0p2_to_0p4_C1,
+                                            mdp_scale_0p2_to_0p4_C2,
+                                            mdp_scale_0p2_to_0p4_C3);
+                               }
+                               ppp_scale_config |= (SCALE_D0_SET << 2);
+                       } else
+                               ppp_scale_config |= BIT(0);
+
+                       /* y-direction */
+                       if ((dst_roi_height_scale == iBuf->roi.height) &&
+                               !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+                               *pppop_reg_ptr &= ~PPP_OP_SCALE_Y_ON;
+                       } else if (((dst_roi_height_scale * 10) /
+                                       iBuf->roi.height) > 8) {
+                               if ((use_pr)
+                                   && (mdp_scale_0p8_to_8p0_mode !=
+                                       MDP_SCALE_PR)) {
+                                       mdp_scale_0p8_to_8p0_mode =
+                                           MDP_SCALE_PR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P8_TO_8P0_INDEX,
+                                            mdp_scale_pixel_repeat_C0,
+                                            mdp_scale_pixel_repeat_C1,
+                                            mdp_scale_pixel_repeat_C2,
+                                            mdp_scale_pixel_repeat_C3);
+                               } else if ((!use_pr)
+                                          && (mdp_scale_0p8_to_8p0_mode !=
+                                              MDP_SCALE_FIR)) {
+                                       mdp_scale_0p8_to_8p0_mode =
+                                           MDP_SCALE_FIR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P8_TO_8P0_INDEX,
+                                            mdp_scale_0p8_to_8p0_C0,
+                                            mdp_scale_0p8_to_8p0_C1,
+                                            mdp_scale_0p8_to_8p0_C2,
+                                            mdp_scale_0p8_to_8p0_C3);
+                               }
+                               ppp_scale_config |= (SCALE_U1_SET << 4);
+                       } else
+                           if (((dst_roi_height_scale * 10) /
+                                iBuf->roi.height) > 6) {
+                               if ((use_pr)
+                                   && (mdp_scale_0p6_to_0p8_mode !=
+                                       MDP_SCALE_PR)) {
+                                       mdp_scale_0p6_to_0p8_mode =
+                                           MDP_SCALE_PR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P6_TO_0P8_INDEX,
+                                            mdp_scale_pixel_repeat_C0,
+                                            mdp_scale_pixel_repeat_C1,
+                                            mdp_scale_pixel_repeat_C2,
+                                            mdp_scale_pixel_repeat_C3);
+                               } else if ((!use_pr)
+                                          && (mdp_scale_0p6_to_0p8_mode !=
+                                              MDP_SCALE_FIR)) {
+                                       mdp_scale_0p6_to_0p8_mode =
+                                           MDP_SCALE_FIR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P6_TO_0P8_INDEX,
+                                            mdp_scale_0p6_to_0p8_C0,
+                                            mdp_scale_0p6_to_0p8_C1,
+                                            mdp_scale_0p6_to_0p8_C2,
+                                            mdp_scale_0p6_to_0p8_C3);
+                               }
+                               ppp_scale_config |= (SCALE_D2_SET << 4);
+                       } else
+                           if (((dst_roi_height_scale * 10) /
+                                iBuf->roi.height) > 4) {
+                               if ((use_pr)
+                                   && (mdp_scale_0p4_to_0p6_mode !=
+                                       MDP_SCALE_PR)) {
+                                       mdp_scale_0p4_to_0p6_mode =
+                                           MDP_SCALE_PR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P4_TO_0P6_INDEX,
+                                            mdp_scale_pixel_repeat_C0,
+                                            mdp_scale_pixel_repeat_C1,
+                                            mdp_scale_pixel_repeat_C2,
+                                            mdp_scale_pixel_repeat_C3);
+                               } else if ((!use_pr)
+                                          && (mdp_scale_0p4_to_0p6_mode !=
+                                              MDP_SCALE_FIR)) {
+                                       mdp_scale_0p4_to_0p6_mode =
+                                           MDP_SCALE_FIR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P4_TO_0P6_INDEX,
+                                            mdp_scale_0p4_to_0p6_C0,
+                                            mdp_scale_0p4_to_0p6_C1,
+                                            mdp_scale_0p4_to_0p6_C2,
+                                            mdp_scale_0p4_to_0p6_C3);
+                               }
+                               ppp_scale_config |= (SCALE_D1_SET << 4);
+                       } else
+                           if (((dst_roi_height_scale * 4) /
+                                iBuf->roi.height) >= 1) {
+                               if ((use_pr)
+                                   && (mdp_scale_0p2_to_0p4_mode !=
+                                       MDP_SCALE_PR)) {
+                                       mdp_scale_0p2_to_0p4_mode =
+                                           MDP_SCALE_PR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P2_TO_0P4_INDEX,
+                                            mdp_scale_pixel_repeat_C0,
+                                            mdp_scale_pixel_repeat_C1,
+                                            mdp_scale_pixel_repeat_C2,
+                                            mdp_scale_pixel_repeat_C3);
+                               } else if ((!use_pr)
+                                          && (mdp_scale_0p2_to_0p4_mode !=
+                                              MDP_SCALE_FIR)) {
+                                       mdp_scale_0p2_to_0p4_mode =
+                                           MDP_SCALE_FIR;
+                                       mdp_update_scale_table
+                                           (MDP_SCALE_0P2_TO_0P4_INDEX,
+                                            mdp_scale_0p2_to_0p4_C0,
+                                            mdp_scale_0p2_to_0p4_C1,
+                                            mdp_scale_0p2_to_0p4_C2,
+                                            mdp_scale_0p2_to_0p4_C3);
+                               }
+                               ppp_scale_config |= (SCALE_D0_SET << 4);
+                       } else
+                               ppp_scale_config |= BIT(1);
+
+                       if (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING) {
+                               ppp_scale_config |= BIT(7);
+                               MDP_OUTP(MDP_BASE + 0x50020,
+                                               iBuf->mdpImg.sp_value);
+                       }
+
+                       MDP_OUTP(MDP_BASE + 0x10230, ppp_scale_config);
+               } else {
+                       iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
+               }
+       }
+}
+
+void mdp_adjust_start_addr(uint8 **src0,
+                          uint8 **src1,
+                          int v_slice,
+                          int h_slice,
+                          int x,
+                          int y,
+                          uint32 width,
+                          uint32 height, int bpp, MDPIBUF *iBuf, int layer)
+{
+       switch (layer) {
+       case 0:
+               MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0200, (y << 16) | (x));
+               MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0208,
+                        (height << 16) | (width));
+               break;
+
+       case 1:
+               /* MDP 3.1 HW bug workaround */
+               if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
+                       *src0 += (x + y * width) * bpp;
+                       x = y = 0;
+                       width = iBuf->roi.dst_width;
+                       height = iBuf->roi.dst_height;
+               }
+
+               MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0204, (y << 16) | (x));
+               MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x020c,
+                        (height << 16) | (width));
+               break;
+
+       case 2:
+               MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x019c, (y << 16) | (x));
+               break;
+       }
+}
+
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+                       uint32 *alpha,
+                       uint32 *tpVal,
+                       uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
+{
+       int bg_alpha;
+
+       *alpha = iBuf->mdpImg.alpha;
+       *tpVal = iBuf->mdpImg.tpVal;
+
+       if (iBuf->mdpImg.mdpOp & MDPOP_FG_PM_ALPHA) {
+               *pppop_reg_ptr |= PPP_OP_ROT_ON |
+                   PPP_OP_BLEND_ON | PPP_OP_BLEND_CONSTANT_ALPHA;
+
+               bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
+                               PPP_BLEND_BG_ALPHA_REVERSE;
+
+               if (perPixelAlpha)
+                       bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
+               else
+                       bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
+
+               outpdw(MDP_BASE + 0x70010, bg_alpha);
+
+               if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+                       *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
+       } else if (perPixelAlpha) {
+               *pppop_reg_ptr |= PPP_OP_ROT_ON |
+                   PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
+       } else {
+               if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+                   && (iBuf->mdpImg.alpha == 0xff)) {
+                       iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+               }
+
+               if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+                   || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+                       *pppop_reg_ptr |=
+                           PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+                           PPP_OP_BLEND_CONSTANT_ALPHA |
+                           PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
+               }
+
+               if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+                       *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
+       }
+}
diff --git a/drivers/staging/msm/mdp_vsync.c b/drivers/staging/msm/mdp_vsync.c
new file mode 100644 (file)
index 0000000..bbd4560
--- /dev/null
@@ -0,0 +1,389 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <mach/gpio.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mddihost.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define MDP_SYNC_CFG_0         0x100
+#define MDP_SYNC_STATUS_0      0x10c
+#define MDP_PRIM_VSYNC_OUT_CTRL        0x118
+#define MDP_PRIM_VSYNC_INIT_VAL        0x128
+#else
+#define MDP_SYNC_CFG_0         0x300
+#define MDP_SYNC_STATUS_0      0x30c
+#define MDP_PRIM_VSYNC_OUT_CTRL        0x318
+#define MDP_PRIM_VSYNC_INIT_VAL        0x328
+#endif
+
+extern mddi_lcd_type mddi_lcd_idx;
+extern spinlock_t mdp_spin_lock;
+extern struct workqueue_struct *mdp_vsync_wq;
+extern int lcdc_mode;
+extern int vsync_mode;
+
+#ifdef MDP_HW_VSYNC
+int vsync_above_th = 4;
+int vsync_start_th = 1;
+int vsync_load_cnt;
+
+struct clk *mdp_vsync_clk;
+
+void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd)
+{
+       if (mfd->use_mdp_vsync)
+               clk_enable(mdp_vsync_clk);
+}
+
+void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd)
+{
+       if (mfd->use_mdp_vsync)
+               clk_disable(mdp_vsync_clk);
+}
+#endif
+
+static void mdp_set_vsync(unsigned long data)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+       struct msm_fb_panel_data *pdata = NULL;
+
+       pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+       if ((pdata) && (pdata->set_vsync_notifier == NULL))
+               return;
+
+       init_timer(&mfd->vsync_resync_timer);
+       mfd->vsync_resync_timer.function = mdp_set_vsync;
+       mfd->vsync_resync_timer.data = data;
+       mfd->vsync_resync_timer.expires =
+           jiffies + mfd->panel_info.lcd.vsync_notifier_period;
+       add_timer(&mfd->vsync_resync_timer);
+
+       if ((mfd->panel_info.lcd.vsync_enable) && (mfd->panel_power_on)
+           && (!mfd->vsync_handler_pending)) {
+               mfd->vsync_handler_pending = TRUE;
+               if (!queue_work(mdp_vsync_wq, &mfd->vsync_resync_worker)) {
+                       MSM_FB_INFO
+                           ("mdp_set_vsync: can't queue_work! -> needs to increase vsync_resync_timer_duration\n");
+               }
+       } else {
+               MSM_FB_DEBUG
+                   ("mdp_set_vsync failed!  EN:%d  PWR:%d  PENDING:%d\n",
+                    mfd->panel_info.lcd.vsync_enable, mfd->panel_power_on,
+                    mfd->vsync_handler_pending);
+       }
+}
+
+static void mdp_vsync_handler(void *data)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+
+       if (mfd->use_mdp_vsync) {
+#ifdef MDP_HW_VSYNC
+               if (mfd->panel_power_on)
+                       MDP_OUTP(MDP_BASE + MDP_SYNC_STATUS_0, vsync_load_cnt);
+
+               mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+#endif
+       } else {
+               mfd->last_vsync_timetick = ktime_get_real();
+       }
+
+       mfd->vsync_handler_pending = FALSE;
+}
+
+irqreturn_t mdp_hw_vsync_handler_proxy(int irq, void *data)
+{
+       /*
+        * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
+        * but getting inaccurate timing in mdp_vsync_handler()
+        * disable_irq(MDP_HW_VSYNC_IRQ);
+        */
+       mdp_vsync_handler(data);
+
+       return IRQ_HANDLED;
+}
+
+#ifdef MDP_HW_VSYNC
+static void mdp_set_sync_cfg_0(struct msm_fb_data_type *mfd, int vsync_cnt)
+{
+       unsigned long cfg;
+
+       cfg = mfd->total_lcd_lines - 1;
+       cfg <<= MDP_SYNCFG_HGT_LOC;
+       if (mfd->panel_info.lcd.hw_vsync_mode)
+               cfg |= MDP_SYNCFG_VSYNC_EXT_EN;
+       cfg |= (MDP_SYNCFG_VSYNC_INT_EN | vsync_cnt);
+
+       MDP_OUTP(MDP_BASE + MDP_SYNC_CFG_0, cfg);
+}
+#endif
+
+void mdp_config_vsync(struct msm_fb_data_type *mfd)
+{
+
+       /* vsync on primary lcd only for now */
+       if ((mfd->dest != DISPLAY_LCD) || (mfd->panel_info.pdest != DISPLAY_1)
+           || (!vsync_mode)) {
+               goto err_handle;
+       }
+
+       if (mfd->panel_info.lcd.vsync_enable) {
+               mfd->total_porch_lines = mfd->panel_info.lcd.v_back_porch +
+                   mfd->panel_info.lcd.v_front_porch +
+                   mfd->panel_info.lcd.v_pulse_width;
+               mfd->total_lcd_lines =
+                   mfd->panel_info.yres + mfd->total_porch_lines;
+               mfd->lcd_ref_usec_time =
+                   100000000 / mfd->panel_info.lcd.refx100;
+               mfd->vsync_handler_pending = FALSE;
+               mfd->last_vsync_timetick.tv.sec = 0;
+               mfd->last_vsync_timetick.tv.nsec = 0;
+
+#ifdef MDP_HW_VSYNC
+               if (mdp_vsync_clk == NULL)
+                       mdp_vsync_clk = clk_get(NULL, "mdp_vsync_clk");
+
+               if (IS_ERR(mdp_vsync_clk)) {
+                       printk(KERN_ERR "error: can't get mdp_vsync_clk!\n");
+                       mfd->use_mdp_vsync = 0;
+               } else
+                       mfd->use_mdp_vsync = 1;
+
+               if (mfd->use_mdp_vsync) {
+                       uint32 vsync_cnt_cfg, vsync_cnt_cfg_dem;
+                       uint32 mdp_vsync_clk_speed_hz;
+
+                       mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk);
+
+                       if (mdp_vsync_clk_speed_hz == 0) {
+                               mfd->use_mdp_vsync = 0;
+                       } else {
+                               /*
+                                * Do this calculation in 2 steps for
+                                * rounding uint32 properly.
+                                */
+                               vsync_cnt_cfg_dem =
+                                   (mfd->panel_info.lcd.refx100 *
+                                    mfd->total_lcd_lines) / 100;
+                               vsync_cnt_cfg =
+                                   (mdp_vsync_clk_speed_hz) /
+                                   vsync_cnt_cfg_dem;
+
+                               /* MDP cmd block enable */
+                               mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
+                                             FALSE);
+                               mdp_hw_vsync_clk_enable(mfd);
+
+                               mdp_set_sync_cfg_0(mfd, vsync_cnt_cfg);
+
+                               /*
+                                * load the last line + 1 to be in the
+                                * safety zone
+                                */
+                               vsync_load_cnt = mfd->panel_info.yres;
+
+                               /* line counter init value at the next pulse */
+                               MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_INIT_VAL,
+                                                       vsync_load_cnt);
+
+                               /*
+                                * external vsync source pulse width and
+                                * polarity flip
+                                */
+                               MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_OUT_CTRL,
+                                                       BIT(30) | BIT(0));
+
+
+                               /* threshold */
+                               MDP_OUTP(MDP_BASE + 0x200,
+                                        (vsync_above_th << 16) |
+                                        (vsync_start_th));
+
+                               mdp_hw_vsync_clk_disable(mfd);
+                               /* MDP cmd block disable */
+                               mdp_pipe_ctrl(MDP_CMD_BLOCK,
+                                             MDP_BLOCK_POWER_OFF, FALSE);
+                       }
+               }
+#else
+               mfd->use_mdp_vsync = 0;
+               hrtimer_init(&mfd->dma_hrtimer, CLOCK_MONOTONIC,
+                            HRTIMER_MODE_REL);
+               mfd->dma_hrtimer.function = mdp_dma2_vsync_hrtimer_handler;
+               mfd->vsync_width_boundary = vmalloc(mfd->panel_info.xres * 4);
+#endif
+
+               mfd->channel_irq = 0;
+               if (mfd->panel_info.lcd.hw_vsync_mode) {
+                       u32 vsync_gpio = mfd->vsync_gpio;
+                       u32 ret;
+
+                       if (vsync_gpio == -1) {
+                               MSM_FB_INFO("vsync_gpio not defined!\n");
+                               goto err_handle;
+                       }
+
+                       ret = gpio_tlmm_config(GPIO_CFG
+                                       (vsync_gpio,
+                                       (mfd->use_mdp_vsync) ? 1 : 0,
+                                       GPIO_INPUT,
+                                       GPIO_PULL_DOWN,
+                                       GPIO_2MA),
+                                       GPIO_ENABLE);
+                       if (ret)
+                               goto err_handle;
+
+                       if (!mfd->use_mdp_vsync) {
+                               mfd->channel_irq = MSM_GPIO_TO_INT(vsync_gpio);
+                               if (request_irq
+                                   (mfd->channel_irq,
+                                    &mdp_hw_vsync_handler_proxy,
+                                    IRQF_TRIGGER_FALLING, "VSYNC_GPIO",
+                                    (void *)mfd)) {
+                                       MSM_FB_INFO
+                                       ("irq=%d failed! vsync_gpio=%d\n",
+                                               mfd->channel_irq,
+                                               vsync_gpio);
+                                       goto err_handle;
+                               }
+                       }
+               }
+
+               mdp_set_vsync((unsigned long)mfd);
+       }
+
+       return;
+
+err_handle:
+       if (mfd->vsync_width_boundary)
+               vfree(mfd->vsync_width_boundary);
+       mfd->panel_info.lcd.vsync_enable = FALSE;
+       printk(KERN_ERR "%s: failed!\n", __func__);
+}
+
+void mdp_vsync_resync_workqueue_handler(struct work_struct *work)
+{
+       struct msm_fb_data_type *mfd = NULL;
+       int vsync_fnc_enabled = FALSE;
+       struct msm_fb_panel_data *pdata = NULL;
+
+       mfd = container_of(work, struct msm_fb_data_type, vsync_resync_worker);
+
+       if (mfd) {
+               if (mfd->panel_power_on) {
+                       pdata =
+                           (struct msm_fb_panel_data *)mfd->pdev->dev.
+                           platform_data;
+
+                       /*
+                        * we need to turn on MDP power if it uses MDP vsync
+                        * HW block in SW mode
+                        */
+                       if ((!mfd->panel_info.lcd.hw_vsync_mode) &&
+                           (mfd->use_mdp_vsync) &&
+                           (pdata) && (pdata->set_vsync_notifier != NULL)) {
+                               /*
+                                * enable pwr here since we can't enable it in
+                                * vsync callback in isr mode
+                                */
+                               mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
+                                             FALSE);
+                       }
+
+                       if (pdata->set_vsync_notifier != NULL) {
+                               vsync_fnc_enabled = TRUE;
+                               pdata->set_vsync_notifier(mdp_vsync_handler,
+                                                         (void *)mfd);
+                       }
+               }
+       }
+
+       if ((mfd) && (!vsync_fnc_enabled))
+               mfd->vsync_handler_pending = FALSE;
+}
+
+boolean mdp_hw_vsync_set_handler(msm_fb_vsync_handler_type handler, void *data)
+{
+       /*
+        * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
+        * but getting inaccurate timing in mdp_vsync_handler()
+        * enable_irq(MDP_HW_VSYNC_IRQ);
+        */
+
+       return TRUE;
+}
+
+uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd)
+{
+       uint32 elapsed_usec_time;
+       uint32 lcd_line;
+       ktime_t last_vsync_timetick_local;
+       ktime_t curr_time;
+       unsigned long flag;
+
+       if ((!mfd->panel_info.lcd.vsync_enable) || (!vsync_mode))
+               return 0;
+
+       spin_lock_irqsave(&mdp_spin_lock, flag);
+       last_vsync_timetick_local = mfd->last_vsync_timetick;
+       spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+       curr_time = ktime_get_real();
+       elapsed_usec_time =
+           ((curr_time.tv.sec - last_vsync_timetick_local.tv.sec) * 1000000) +
+           ((curr_time.tv.nsec - last_vsync_timetick_local.tv.nsec) / 1000);
+
+       elapsed_usec_time = elapsed_usec_time % mfd->lcd_ref_usec_time;
+
+       /* lcd line calculation referencing to line counter = 0 */
+       lcd_line =
+           (elapsed_usec_time * mfd->total_lcd_lines) / mfd->lcd_ref_usec_time;
+
+       /* lcd line adjusment referencing to the actual line counter at vsync */
+       lcd_line =
+           (mfd->total_lcd_lines - mfd->panel_info.lcd.v_back_porch +
+            lcd_line) % (mfd->total_lcd_lines + 1);
+
+       if (lcd_line > mfd->total_lcd_lines) {
+               MSM_FB_INFO
+                   ("mdp_get_lcd_line_counter: mdp_lcd_rd_cnt >= mfd->total_lcd_lines error!\n");
+       }
+
+       return lcd_line;
+}
diff --git a/drivers/staging/msm/memory.c b/drivers/staging/msm/memory.c
new file mode 100644 (file)
index 0000000..cc80fdf
--- /dev/null
@@ -0,0 +1,214 @@
+/* arch/arm/mach-msm/memory.c
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2010, Code Aurora Forum. 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/mm.h>
+#include <linux/mm_types.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+#include "memory_ll.h"
+#include <asm/cacheflush.h>
+#if defined(CONFIG_MSM_NPA_REMOTE)
+#include "npa_remote.h"
+#include <linux/completion.h>
+#include <linux/err.h>
+#endif
+
+int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
+                           unsigned long pfn, unsigned long size, pgprot_t prot)
+{
+       unsigned long pfn_addr = pfn << PAGE_SHIFT;
+/*
+       if ((pfn_addr >= 0x88000000) && (pfn_addr < 0xD0000000)) {
+               prot = pgprot_device(prot);
+               printk("remapping device %lx\n", prot);
+       }
+*/
+       panic("Memory remap PFN stuff not done\n");
+       return remap_pfn_range(vma, addr, pfn, size, prot);
+}
+
+void *zero_page_strongly_ordered;
+
+static void map_zero_page_strongly_ordered(void)
+{
+       if (zero_page_strongly_ordered)
+               return;
+/*
+       zero_page_strongly_ordered =
+               ioremap_strongly_ordered(page_to_pfn(empty_zero_page)
+               << PAGE_SHIFT, PAGE_SIZE);
+*/
+       panic("Strongly ordered memory functions not implemented\n");
+}
+
+void write_to_strongly_ordered_memory(void)
+{
+       map_zero_page_strongly_ordered();
+       *(int *)zero_page_strongly_ordered = 0;
+}
+EXPORT_SYMBOL(write_to_strongly_ordered_memory);
+
+void flush_axi_bus_buffer(void)
+{
+       __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
+                                   : : "r" (0) : "memory");
+       write_to_strongly_ordered_memory();
+}
+
+#define CACHE_LINE_SIZE 32
+
+/* These cache related routines make the assumption that the associated
+ * physical memory is contiguous. They will operate on all (L1
+ * and L2 if present) caches.
+ */
+void clean_and_invalidate_caches(unsigned long vstart,
+       unsigned long length, unsigned long pstart)
+{
+       unsigned long vaddr;
+
+       for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
+               asm ("mcr p15, 0, %0, c7, c14, 1" : : "r" (vaddr));
+#ifdef CONFIG_OUTER_CACHE
+       outer_flush_range(pstart, pstart + length);
+#endif
+       asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+       asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
+
+       flush_axi_bus_buffer();
+}
+
+void clean_caches(unsigned long vstart,
+       unsigned long length, unsigned long pstart)
+{
+       unsigned long vaddr;
+
+       for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
+               asm ("mcr p15, 0, %0, c7, c10, 1" : : "r" (vaddr));
+#ifdef CONFIG_OUTER_CACHE
+       outer_clean_range(pstart, pstart + length);
+#endif
+       asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+       asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
+
+       flush_axi_bus_buffer();
+}
+
+void invalidate_caches(unsigned long vstart,
+       unsigned long length, unsigned long pstart)
+{
+       unsigned long vaddr;
+
+       for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
+               asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (vaddr));
+#ifdef CONFIG_OUTER_CACHE
+       outer_inv_range(pstart, pstart + length);
+#endif
+       asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+       asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
+
+       flush_axi_bus_buffer();
+}
+
+void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
+{
+       void *unused_addr = NULL;
+       unsigned long addr, tmp_size, unused_size;
+
+       /* Allocate maximum size needed, see where it ends up.
+        * Then free it -- in this path there are no other allocators
+        * so we can depend on getting the same address back
+        * when we allocate a smaller piece that is aligned
+        * at the end (if necessary) and the piece we really want,
+        * then free the unused first piece.
+        */
+
+       tmp_size = size + alignment - PAGE_SIZE;
+       addr = (unsigned long)alloc_bootmem(tmp_size);
+       free_bootmem(__pa(addr), tmp_size);
+
+       unused_size = alignment - (addr % alignment);
+       if (unused_size)
+               unused_addr = alloc_bootmem(unused_size);
+
+       addr = (unsigned long)alloc_bootmem(size);
+       if (unused_size)
+               free_bootmem(__pa(unused_addr), unused_size);
+
+       return (void *)addr;
+}
+
+#if defined(CONFIG_MSM_NPA_REMOTE)
+struct npa_client *npa_memory_client;
+#endif
+
+static int change_memory_power_state(unsigned long start_pfn,
+       unsigned long nr_pages, int state)
+{
+#if defined(CONFIG_MSM_NPA_REMOTE)
+       static atomic_t node_created_flag = ATOMIC_INIT(1);
+#else
+       unsigned long start;
+       unsigned long size;
+       unsigned long virtual;
+#endif
+       int rc = 0;
+
+#if defined(CONFIG_MSM_NPA_REMOTE)
+       if (atomic_dec_and_test(&node_created_flag)) {
+               /* Create NPA 'required' client. */
+               npa_memory_client = npa_create_sync_client(NPA_MEMORY_NODE_NAME,
+                       "memory node", NPA_CLIENT_REQUIRED);
+               if (IS_ERR(npa_memory_client)) {
+                       rc = PTR_ERR(npa_memory_client);
+                       return rc;
+               }
+       }
+
+       rc = npa_issue_required_request(npa_memory_client, state);
+#else
+       if (state == MEMORY_DEEP_POWERDOWN) {
+               /* simulate turning off memory by writing bit pattern into it */
+               start = start_pfn << PAGE_SHIFT;
+               size = nr_pages << PAGE_SHIFT;
+               virtual = __phys_to_virt(start);
+               memset((void *)virtual, 0x27, size);
+       }
+#endif
+       return rc;
+}
+
+int platform_physical_remove_pages(unsigned long start_pfn,
+       unsigned long nr_pages)
+{
+       return change_memory_power_state(start_pfn, nr_pages,
+               MEMORY_DEEP_POWERDOWN);
+}
+
+int platform_physical_add_pages(unsigned long start_pfn,
+       unsigned long nr_pages)
+{
+       return change_memory_power_state(start_pfn, nr_pages, MEMORY_ACTIVE);
+}
+
+int platform_physical_low_power_pages(unsigned long start_pfn,
+       unsigned long nr_pages)
+{
+       return change_memory_power_state(start_pfn, nr_pages,
+               MEMORY_SELF_REFRESH);
+}
diff --git a/drivers/staging/msm/memory_ll.h b/drivers/staging/msm/memory_ll.h
new file mode 100644 (file)
index 0000000..18a239a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2010, Code Aurora Forum. 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.
+ *
+ */
+#ifndef __ASM_ARCH_MEMORY_LL_H
+#define __ASM_ARCH_MEMORY_LL_H
+
+#define MAX_PHYSMEM_BITS 32
+#define SECTION_SIZE_BITS 25
+
+#define HAS_ARCH_IO_REMAP_PFN_RANGE
+
+#ifndef __ASSEMBLY__
+void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment);
+void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long);
+void clean_caches(unsigned long, unsigned long, unsigned long);
+void invalidate_caches(unsigned long, unsigned long, unsigned long);
+int platform_physical_remove_pages(unsigned long, unsigned long);
+int platform_physical_add_pages(unsigned long, unsigned long);
+int platform_physical_low_power_pages(unsigned long, unsigned long);
+
+#ifdef CONFIG_ARCH_MSM_ARM11
+void write_to_strongly_ordered_memory(void);
+
+#include <asm/mach-types.h>
+
+#define arch_barrier_extra() do \
+       { if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa())  \
+               write_to_strongly_ordered_memory(); \
+       } while (0)
+#endif
+
+#ifdef CONFIG_CACHE_L2X0
+extern void l2x0_cache_sync(void);
+#define finish_arch_switch(prev)     do { l2x0_cache_sync(); } while (0)
+#endif
+
+#endif
+
+#ifdef CONFIG_ARCH_MSM_SCORPION
+#define arch_has_speculative_dfetch()  1
+#endif
+
+#endif
+
+/* these correspond to values known by the modem */
+#define MEMORY_DEEP_POWERDOWN  0
+#define MEMORY_SELF_REFRESH    1
+#define MEMORY_ACTIVE          2
+
+#define NPA_MEMORY_NODE_NAME   "/mem/ebi1/cs1"
diff --git a/drivers/staging/msm/msm_fb.c b/drivers/staging/msm/msm_fb.c
new file mode 100644 (file)
index 0000000..af5620e
--- /dev/null
@@ -0,0 +1,2354 @@
+/*
+ *
+ * Core MSM framebuffer driver.
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2008-2010, Code Aurora Forum. 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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include "msm_mdp.h"
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <mach/board.h>
+#include <linux/uaccess.h>
+
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+#include <linux/console.h>
+#include <linux/leds.h>
+#include <asm/dma-mapping.h>
+
+
+#define MSM_FB_C
+#include "msm_fb.h"
+#include "mddihosti.h"
+#include "tvenc.h"
+#include "mdp.h"
+#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_LOGO
+#define INIT_IMAGE_FILE "/logo.rle"
+extern int load_565rle_image(char *filename);
+#endif
+
+
+#define pgprot_noncached(prot) \
+       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
+#define pgprot_writecombine(prot) \
+       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
+#define pgprot_device(prot) \
+       __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_DEV_NONSHARED)
+#define pgprot_writethroughcache(prot) \
+       __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITETHROUGH)
+#define pgprot_writebackcache(prot) \
+       __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEBACK)
+#define pgprot_writebackwacache(prot) \
+       __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEALLOC)
+
+static unsigned char *fbram;
+static unsigned char *fbram_phys;
+static int fbram_size;
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+int vsync_mode = 1;
+
+#define MAX_FBI_LIST 32
+static struct fb_info *fbi_list[MAX_FBI_LIST];
+static int fbi_list_index;
+
+static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST];
+static int mfd_list_index;
+
+static u32 msm_fb_pseudo_palette[16] = {
+       0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
+       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
+};
+
+u32 msm_fb_debug_enabled;
+/* Setting msm_fb_msg_level to 8 prints out ALL messages */
+u32 msm_fb_msg_level = 7;
+
+/* Setting mddi_msg_level to 8 prints out ALL messages */
+u32 mddi_msg_level = 5;
+
+extern int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
+extern unsigned long mdp_timer_duration;
+
+static int msm_fb_register(struct msm_fb_data_type *mfd);
+static int msm_fb_open(struct fb_info *info, int user);
+static int msm_fb_release(struct fb_info *info, int user);
+static int msm_fb_pan_display(struct fb_var_screeninfo *var,
+                             struct fb_info *info);
+static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd);
+int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd);
+static int msm_fb_check_var(struct fb_var_screeninfo *var,
+                           struct fb_info *info);
+static int msm_fb_set_par(struct fb_info *info);
+static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
+                           boolean op_enable);
+static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd);
+static int msm_fb_resume_sub(struct msm_fb_data_type *mfd);
+static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
+                       unsigned long arg);
+static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma);
+
+#ifdef MSM_FB_ENABLE_DBGFS
+
+#define MSM_FB_MAX_DBGFS 1024
+#define MAX_BACKLIGHT_BRIGHTNESS 255
+
+int msm_fb_debugfs_file_index;
+struct dentry *msm_fb_debugfs_root;
+struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS];
+
+struct dentry *msm_fb_get_debugfs_root(void)
+{
+       if (msm_fb_debugfs_root == NULL)
+               msm_fb_debugfs_root = debugfs_create_dir("msm_fb", NULL);
+
+       return msm_fb_debugfs_root;
+}
+
+void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
+                               u32 *var)
+{
+       if (msm_fb_debugfs_file_index >= MSM_FB_MAX_DBGFS)
+               return;
+
+       msm_fb_debugfs_file[msm_fb_debugfs_file_index++] =
+           debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var);
+}
+#endif
+
+int msm_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+       if (!mfd->cursor_update)
+               return -ENODEV;
+
+       return mfd->cursor_update(info, cursor);
+}
+
+static int msm_fb_resource_initialized;
+
+#ifndef CONFIG_FB_BACKLIGHT
+static int lcd_backlight_registered;
+
+static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev,
+                                       enum led_brightness value)
+{
+       struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
+       int bl_lvl;
+
+       if (value > MAX_BACKLIGHT_BRIGHTNESS)
+               value = MAX_BACKLIGHT_BRIGHTNESS;
+
+       /* This maps android backlight level 0 to 255 into
+          driver backlight level 0 to bl_max with rounding */
+       bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS)
+               /(2 * MAX_BACKLIGHT_BRIGHTNESS);
+
+       if (!bl_lvl && value)
+               bl_lvl = 1;
+
+       msm_fb_set_backlight(mfd, bl_lvl, 1);
+}
+
+static struct led_classdev backlight_led = {
+       .name           = "lcd-backlight",
+       .brightness     = MAX_BACKLIGHT_BRIGHTNESS,
+       .brightness_set = msm_fb_set_bl_brightness,
+};
+#endif
+
+static struct msm_fb_platform_data *msm_fb_pdata;
+
+int msm_fb_detect_client(const char *name)
+{
+       int ret = -EPERM;
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+       u32 id;
+#endif
+
+       if (msm_fb_pdata && msm_fb_pdata->detect_client) {
+               ret = msm_fb_pdata->detect_client(name);
+
+               /* if it's non mddi panel, we need to pre-scan
+                  mddi client to see if we can disable mddi host */
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+               if (!ret && msm_fb_pdata->mddi_prescan)
+                       id = mddi_get_client_id();
+#endif
+       }
+
+       return ret;
+}
+
+static int msm_fb_probe(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+       int rc;
+
+       MSM_FB_DEBUG("msm_fb_probe\n");
+
+       if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+               msm_fb_pdata = pdev->dev.platform_data;
+               fbram_size =
+                       pdev->resource[0].end - pdev->resource[0].start + 1;
+               fbram_phys = (char *)pdev->resource[0].start;
+               fbram = ioremap((unsigned long)fbram_phys, fbram_size);
+
+               if (!fbram) {
+                       printk(KERN_ERR "fbram ioremap failed!\n");
+                       return -ENOMEM;
+               }
+               MSM_FB_INFO("msm_fb_probe:  phy_Addr = 0x%x virt = 0x%x\n",
+                            (int)fbram_phys, (int)fbram);
+
+               msm_fb_resource_initialized = 1;
+               return 0;
+       }
+
+       if (!msm_fb_resource_initialized)
+               return -EPERM;
+
+       mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+               return -ENOMEM;
+
+       mfd->panel_info.frame_count = 0;
+       mfd->bl_level = mfd->panel_info.bl_max;
+
+       if (mfd->panel_info.type == LCDC_PANEL)
+               mfd->allow_set_offset =
+               msm_fb_pdata->allow_set_offset != NULL ?
+               msm_fb_pdata->allow_set_offset() : 0;
+       else
+               mfd->allow_set_offset = 0;
+
+       rc = msm_fb_register(mfd);
+       if (rc)
+               return rc;
+
+#ifdef CONFIG_FB_BACKLIGHT
+       msm_fb_config_backlight(mfd);
+#else
+       /* android supports only one lcd-backlight/lcd for now */
+       if (!lcd_backlight_registered) {
+               if (led_classdev_register(&pdev->dev, &backlight_led))
+                       printk(KERN_ERR "led_classdev_register failed\n");
+               else
+                       lcd_backlight_registered = 1;
+       }
+#endif
+
+       pdev_list[pdev_list_cnt++] = pdev;
+       return 0;
+}
+
+static int msm_fb_remove(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+
+       MSM_FB_DEBUG("msm_fb_remove\n");
+
+       mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       if (msm_fb_suspend_sub(mfd))
+               printk(KERN_ERR "msm_fb_remove: can't stop the device %d\n", mfd->index);
+
+       if (mfd->channel_irq != 0)
+               free_irq(mfd->channel_irq, (void *)mfd);
+
+       if (mfd->vsync_width_boundary)
+               vfree(mfd->vsync_width_boundary);
+
+       if (mfd->vsync_resync_timer.function)
+               del_timer(&mfd->vsync_resync_timer);
+
+       if (mfd->refresh_timer.function)
+               del_timer(&mfd->refresh_timer);
+
+       if (mfd->dma_hrtimer.function)
+               hrtimer_cancel(&mfd->dma_hrtimer);
+
+       /* remove /dev/fb* */
+       unregister_framebuffer(mfd->fbi);
+
+#ifdef CONFIG_FB_BACKLIGHT
+       /* remove /sys/class/backlight */
+       backlight_device_unregister(mfd->fbi->bl_dev);
+#else
+       if (lcd_backlight_registered) {
+               lcd_backlight_registered = 0;
+               led_classdev_unregister(&backlight_led);
+       }
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+       if (mfd->sub_dir)
+               debugfs_remove(mfd->sub_dir);
+#endif
+
+       return 0;
+}
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int msm_fb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct msm_fb_data_type *mfd;
+       int ret = 0;
+
+       MSM_FB_DEBUG("msm_fb_suspend\n");
+
+       mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+       if ((!mfd) || (mfd->key != MFD_KEY))
+               return 0;
+
+       acquire_console_sem();
+       fb_set_suspend(mfd->fbi, 1);
+
+       ret = msm_fb_suspend_sub(mfd);
+       if (ret != 0) {
+               printk(KERN_ERR "msm_fb: failed to suspend! %d\n", ret);
+               fb_set_suspend(mfd->fbi, 0);
+       } else {
+               pdev->dev.power.power_state = state;
+       }
+
+       release_console_sem();
+       return ret;
+}
+#else
+#define msm_fb_suspend NULL
+#endif
+
+static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd)
+{
+       int ret = 0;
+
+       if ((!mfd) || (mfd->key != MFD_KEY))
+               return 0;
+
+       /*
+        * suspend this channel
+        */
+       mfd->suspend.sw_refreshing_enable = mfd->sw_refreshing_enable;
+       mfd->suspend.op_enable = mfd->op_enable;
+       mfd->suspend.panel_power_on = mfd->panel_power_on;
+
+       if (mfd->op_enable) {
+               ret =
+                    msm_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
+                                     mfd->suspend.op_enable);
+               if (ret) {
+                       MSM_FB_INFO
+                           ("msm_fb_suspend: can't turn off display!\n");
+                       return ret;
+               }
+               mfd->op_enable = FALSE;
+       }
+       /*
+        * try to power down
+        */
+       mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+       /*
+        * detach display channel irq if there's any
+        * or wait until vsync-resync completes
+        */
+       if ((mfd->dest == DISPLAY_LCD)) {
+               if (mfd->panel_info.lcd.vsync_enable) {
+                       if (mfd->panel_info.lcd.hw_vsync_mode) {
+                               if (mfd->channel_irq != 0)
+                                       disable_irq(mfd->channel_irq);
+                       } else {
+                               volatile boolean vh_pending;
+                               do {
+                                       vh_pending = mfd->vsync_handler_pending;
+                               } while (vh_pending);
+                       }
+               }
+       }
+
+       return 0;
+}
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int msm_fb_resume(struct platform_device *pdev)
+{
+       /* This resume function is called when interrupt is enabled.
+        */
+       int ret = 0;
+       struct msm_fb_data_type *mfd;
+
+       MSM_FB_DEBUG("msm_fb_resume\n");
+
+       mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+       if ((!mfd) || (mfd->key != MFD_KEY))
+               return 0;
+
+       acquire_console_sem();
+       ret = msm_fb_resume_sub(mfd);
+       pdev->dev.power.power_state = PMSG_ON;
+       fb_set_suspend(mfd->fbi, 1);
+       release_console_sem();
+
+       return ret;
+}
+#else
+#define msm_fb_resume NULL
+#endif
+
+static int msm_fb_resume_sub(struct msm_fb_data_type *mfd)
+{
+       int ret = 0;
+
+       if ((!mfd) || (mfd->key != MFD_KEY))
+               return 0;
+
+       /* attach display channel irq if there's any */
+       if (mfd->channel_irq != 0)
+               enable_irq(mfd->channel_irq);
+
+       /* resume state var recover */
+       mfd->sw_refreshing_enable = mfd->suspend.sw_refreshing_enable;
+       mfd->op_enable = mfd->suspend.op_enable;
+
+       if (mfd->suspend.panel_power_on) {
+               ret =
+                    msm_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi,
+                                     mfd->op_enable);
+               if (ret)
+                       MSM_FB_INFO("msm_fb_resume: can't turn on display!\n");
+       }
+
+       return ret;
+}
+
+static struct platform_driver msm_fb_driver = {
+       .probe = msm_fb_probe,
+       .remove = msm_fb_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+       .suspend = msm_fb_suspend,
+       .resume = msm_fb_resume,
+#endif
+       .shutdown = NULL,
+       .driver = {
+                  /* Driver name must match the device name added in platform.c. */
+                  .name = "msm_fb",
+                  },
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void msmfb_early_suspend(struct early_suspend *h)
+{
+       struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+                                                   early_suspend);
+       msm_fb_suspend_sub(mfd);
+}
+
+static void msmfb_early_resume(struct early_suspend *h)
+{
+       struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+                                                   early_suspend);
+       msm_fb_resume_sub(mfd);
+}
+#endif
+
+void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl, u32 save)
+{
+       struct msm_fb_panel_data *pdata;
+
+       pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+       if ((pdata) && (pdata->set_backlight)) {
+               down(&mfd->sem);
+               if ((bkl_lvl != mfd->bl_level) || (!save)) {
+                       u32 old_lvl;
+
+                       old_lvl = mfd->bl_level;
+                       mfd->bl_level = bkl_lvl;
+                       pdata->set_backlight(mfd);
+
+                       if (!save)
+                               mfd->bl_level = old_lvl;
+               }
+               up(&mfd->sem);
+       }
+}
+
+static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
+                           boolean op_enable)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       struct msm_fb_panel_data *pdata = NULL;
+       int ret = 0;
+
+       if (!op_enable)
+               return -EPERM;
+
+       pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+       if ((!pdata) || (!pdata->on) || (!pdata->off)) {
+               printk(KERN_ERR "msm_fb_blank_sub: no panel operation detected!\n");
+               return -ENODEV;
+       }
+
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               if (!mfd->panel_power_on) {
+                       mdelay(100);
+                       ret = pdata->on(mfd->pdev);
+                       if (ret == 0) {
+                               mfd->panel_power_on = TRUE;
+
+                               msm_fb_set_backlight(mfd,
+                                                    mfd->bl_level, 0);
+
+/* ToDo: possible conflict with android which doesn't expect sw refresher */
+/*
+         if (!mfd->hw_refresh)
+         {
+           if ((ret = msm_fb_resume_sw_refresher(mfd)) != 0)
+           {
+             MSM_FB_INFO("msm_fb_blank_sub: msm_fb_resume_sw_refresher failed = %d!\n",ret);
+           }
+         }
+*/
+                       }
+               }
+               break;
+
+       case FB_BLANK_VSYNC_SUSPEND:
+       case FB_BLANK_HSYNC_SUSPEND:
+       case FB_BLANK_NORMAL:
+       case FB_BLANK_POWERDOWN:
+       default:
+               if (mfd->panel_power_on) {
+                       int curr_pwr_state;
+
+                       mfd->op_enable = FALSE;
+                       curr_pwr_state = mfd->panel_power_on;
+                       mfd->panel_power_on = FALSE;
+
+                       mdelay(100);
+                       ret = pdata->off(mfd->pdev);
+                       if (ret)
+                               mfd->panel_power_on = curr_pwr_state;
+
+                       msm_fb_set_backlight(mfd, 0, 0);
+                       mfd->op_enable = TRUE;
+               }
+               break;
+       }
+
+       return ret;
+}
+
+static void msm_fb_fillrect(struct fb_info *info,
+                           const struct fb_fillrect *rect)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+       cfb_fillrect(info, rect);
+       if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+               !mfd->sw_currently_refreshing) {
+               struct fb_var_screeninfo var;
+
+               var = info->var;
+               var.reserved[0] = 0x54445055;
+               var.reserved[1] = (rect->dy << 16) | (rect->dx);
+               var.reserved[2] = ((rect->dy + rect->height) << 16) |
+                   (rect->dx + rect->width);
+
+               msm_fb_pan_display(&var, info);
+       }
+}
+
+static void msm_fb_copyarea(struct fb_info *info,
+                           const struct fb_copyarea *area)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+       cfb_copyarea(info, area);
+       if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+               !mfd->sw_currently_refreshing) {
+               struct fb_var_screeninfo var;
+
+               var = info->var;
+               var.reserved[0] = 0x54445055;
+               var.reserved[1] = (area->dy << 16) | (area->dx);
+               var.reserved[2] = ((area->dy + area->height) << 16) |
+                   (area->dx + area->width);
+
+               msm_fb_pan_display(&var, info);
+       }
+}
+
+static void msm_fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+       cfb_imageblit(info, image);
+       if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+               !mfd->sw_currently_refreshing) {
+               struct fb_var_screeninfo var;
+
+               var = info->var;
+               var.reserved[0] = 0x54445055;
+               var.reserved[1] = (image->dy << 16) | (image->dx);
+               var.reserved[2] = ((image->dy + image->height) << 16) |
+                   (image->dx + image->width);
+
+               msm_fb_pan_display(&var, info);
+       }
+}
+
+static int msm_fb_blank(int blank_mode, struct fb_info *info)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       return msm_fb_blank_sub(blank_mode, info, mfd->op_enable);
+}
+
+static int msm_fb_set_lut(struct fb_cmap *cmap, struct fb_info *info)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+       if (!mfd->lut_update)
+               return -ENODEV;
+
+       mfd->lut_update(info, cmap);
+       return 0;
+}
+
+/*
+ * Custom Framebuffer mmap() function for MSM driver.
+ * Differs from standard mmap() function by allowing for customized
+ * page-protection.
+ */
+static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma)
+{
+       /* Get frame buffer memory range. */
+       unsigned long start = info->fix.smem_start;
+       u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
+       unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       if (off >= len) {
+               /* memory mapped io */
+               off -= len;
+               if (info->var.accel_flags) {
+                       mutex_unlock(&info->lock);
+                       return -EINVAL;
+               }
+               start = info->fix.mmio_start;
+               len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
+       }
+
+       /* Set VM flags. */
+       start &= PAGE_MASK;
+       if ((vma->vm_end - vma->vm_start + off) > len)
+               return -EINVAL;
+       off += start;
+       vma->vm_pgoff = off >> PAGE_SHIFT;
+       /* This is an IO map - tell maydump to skip this VMA */
+       vma->vm_flags |= VM_IO | VM_RESERVED;
+
+       /* Set VM page protection */
+       if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE)
+               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+       else if (mfd->mdp_fb_page_protection ==
+                       MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE)
+               vma->vm_page_prot = pgprot_writethroughcache(vma->vm_page_prot);
+       else if (mfd->mdp_fb_page_protection ==
+                       MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE)
+               vma->vm_page_prot = pgprot_writebackcache(vma->vm_page_prot);
+       else if (mfd->mdp_fb_page_protection ==
+                       MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE)
+               vma->vm_page_prot = pgprot_writebackwacache(vma->vm_page_prot);
+       else
+               vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+       /* Remap the frame buffer I/O range */
+       if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+                               vma->vm_end - vma->vm_start,
+                               vma->vm_page_prot))
+               return -EAGAIN;
+
+       return 0;
+}
+
+static struct fb_ops msm_fb_ops = {
+       .owner = THIS_MODULE,
+       .fb_open = msm_fb_open,
+       .fb_release = msm_fb_release,
+       .fb_read = NULL,
+       .fb_write = NULL,
+       .fb_cursor = NULL,
+       .fb_check_var = msm_fb_check_var,       /* vinfo check */
+       .fb_set_par = msm_fb_set_par,   /* set the video mode according to info->var */
+       .fb_setcolreg = NULL,   /* set color register */
+       .fb_blank = msm_fb_blank,       /* blank display */
+       .fb_pan_display = msm_fb_pan_display,   /* pan display */
+       .fb_fillrect = msm_fb_fillrect, /* Draws a rectangle */
+       .fb_copyarea = msm_fb_copyarea, /* Copy data from area to another */
+       .fb_imageblit = msm_fb_imageblit,       /* Draws a image to the display */
+       .fb_rotate = NULL,
+       .fb_sync = NULL,        /* wait for blit idle, optional */
+       .fb_ioctl = msm_fb_ioctl,       /* perform fb specific ioctl (optional) */
+       .fb_mmap = msm_fb_mmap,
+};
+
+static int msm_fb_register(struct msm_fb_data_type *mfd)
+{
+       int ret = -ENODEV;
+       int bpp;
+       struct msm_panel_info *panel_info = &mfd->panel_info;
+       struct fb_info *fbi = mfd->fbi;
+       struct fb_fix_screeninfo *fix;
+       struct fb_var_screeninfo *var;
+       int *id;
+       int fbram_offset;
+
+       /*
+        * fb info initialization
+        */
+       fix = &fbi->fix;
+       var = &fbi->var;
+
+       fix->type_aux = 0;      /* if type == FB_TYPE_INTERLEAVED_PLANES */
+       fix->visual = FB_VISUAL_TRUECOLOR;      /* True Color */
+       fix->ywrapstep = 0;     /* No support */
+       fix->mmio_start = 0;    /* No MMIO Address */
+       fix->mmio_len = 0;      /* No MMIO Address */
+       fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */
+
+       var->xoffset = 0,       /* Offset from virtual to visible */
+       var->yoffset = 0,       /* resolution */
+       var->grayscale = 0,     /* No graylevels */
+       var->nonstd = 0,        /* standard pixel format */
+       var->activate = FB_ACTIVATE_VBL,        /* activate it at vsync */
+       var->height = -1,       /* height of picture in mm */
+       var->width = -1,        /* width of picture in mm */
+       var->accel_flags = 0,   /* acceleration flags */
+       var->sync = 0,  /* see FB_SYNC_* */
+       var->rotate = 0,        /* angle we rotate counter clockwise */
+       mfd->op_enable = FALSE;
+
+       switch (mfd->fb_imgType) {
+       case MDP_RGB_565:
+               fix->type = FB_TYPE_PACKED_PIXELS;
+               fix->xpanstep = 1;
+               fix->ypanstep = 1;
+               var->vmode = FB_VMODE_NONINTERLACED;
+               var->blue.offset = 0;
+               var->green.offset = 5;
+               var->red.offset = 11;
+               var->blue.length = 5;
+               var->green.length = 6;
+               var->red.length = 5;
+               var->blue.msb_right = 0;
+               var->green.msb_right = 0;
+               var->red.msb_right = 0;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               bpp = 2;
+               break;
+
+       case MDP_RGB_888:
+               fix->type = FB_TYPE_PACKED_PIXELS;
+               fix->xpanstep = 1;
+               fix->ypanstep = 1;
+               var->vmode = FB_VMODE_NONINTERLACED;
+               var->blue.offset = 0;
+               var->green.offset = 8;
+               var->red.offset = 16;
+               var->blue.length = 8;
+               var->green.length = 8;
+               var->red.length = 8;
+               var->blue.msb_right = 0;
+               var->green.msb_right = 0;
+               var->red.msb_right = 0;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               bpp = 3;
+               break;
+
+       case MDP_ARGB_8888:
+               fix->type = FB_TYPE_PACKED_PIXELS;
+               fix->xpanstep = 1;
+               fix->ypanstep = 1;
+               var->vmode = FB_VMODE_NONINTERLACED;
+               var->blue.offset = 0;
+               var->green.offset = 8;
+               var->red.offset = 16;
+               var->blue.length = 8;
+               var->green.length = 8;
+               var->red.length = 8;
+               var->blue.msb_right = 0;
+               var->green.msb_right = 0;
+               var->red.msb_right = 0;
+               var->transp.offset = 24;
+               var->transp.length = 8;
+               bpp = 3;
+               break;
+
+       case MDP_YCRYCB_H2V1:
+               /* ToDo: need to check TV-Out YUV422i framebuffer format */
+               /*       we might need to create new type define */
+               fix->type = FB_TYPE_INTERLEAVED_PLANES;
+               fix->xpanstep = 2;
+               fix->ypanstep = 1;
+               var->vmode = FB_VMODE_NONINTERLACED;
+
+               /* how about R/G/B offset? */
+               var->blue.offset = 0;
+               var->green.offset = 5;
+               var->red.offset = 11;
+               var->blue.length = 5;
+               var->green.length = 6;
+               var->red.length = 5;
+               var->blue.msb_right = 0;
+               var->green.msb_right = 0;
+               var->red.msb_right = 0;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               bpp = 2;
+               break;
+
+       default:
+               MSM_FB_ERR("msm_fb_init: fb %d unkown image type!\n",
+                          mfd->index);
+               return ret;
+       }
+
+       /* The adreno GPU hardware requires that the pitch be aligned to
+          32 pixels for color buffers, so for the cases where the GPU
+          is writing directly to fb0, the framebuffer pitch
+          also needs to be 32 pixel aligned */
+
+       if (mfd->index == 0)
+               fix->line_length = ALIGN(panel_info->xres * bpp, 32);
+       else
+               fix->line_length = panel_info->xres * bpp;
+
+       fix->smem_len = fix->line_length * panel_info->yres * mfd->fb_page;
+
+       mfd->var_xres = panel_info->xres;
+       mfd->var_yres = panel_info->yres;
+
+       var->pixclock = mfd->panel_info.clk_rate;
+       mfd->var_pixclock = var->pixclock;
+
+       var->xres = panel_info->xres;
+       var->yres = panel_info->yres;
+       var->xres_virtual = panel_info->xres;
+       var->yres_virtual = panel_info->yres * mfd->fb_page;
+       var->bits_per_pixel = bpp * 8,  /* FrameBuffer color depth */
+               /*
+                * id field for fb app
+                */
+           id = (int *)&mfd->panel;
+
+#if defined(CONFIG_FB_MSM_MDP22)
+       snprintf(fix->id, sizeof(fix->id), "msmfb22_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP30)
+       snprintf(fix->id, sizeof(fix->id), "msmfb30_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP31)
+       snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP40)
+       snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id);
+#else
+       error CONFIG_FB_MSM_MDP undefined !
+#endif
+        fbi->fbops = &msm_fb_ops;
+       fbi->flags = FBINFO_FLAG_DEFAULT;
+       fbi->pseudo_palette = msm_fb_pseudo_palette;
+
+       mfd->ref_cnt = 0;
+       mfd->sw_currently_refreshing = FALSE;
+       mfd->sw_refreshing_enable = TRUE;
+       mfd->panel_power_on = FALSE;
+
+       mfd->pan_waiting = FALSE;
+       init_completion(&mfd->pan_comp);
+       init_completion(&mfd->refresher_comp);
+       init_MUTEX(&mfd->sem);
+
+       fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
+       fbram += fbram_offset;
+       fbram_phys += fbram_offset;
+       fbram_size -= fbram_offset;
+
+       if (fbram_size < fix->smem_len) {
+               printk(KERN_ERR "error: no more framebuffer memory!\n");
+               return -ENOMEM;
+       }
+
+       fbi->screen_base = fbram;
+       fbi->fix.smem_start = (unsigned long)fbram_phys;
+
+       memset(fbi->screen_base, 0x0, fix->smem_len);
+
+       mfd->op_enable = TRUE;
+       mfd->panel_power_on = FALSE;
+
+       /* cursor memory allocation */
+       if (mfd->cursor_update) {
+               mfd->cursor_buf = dma_alloc_coherent(NULL,
+                                       MDP_CURSOR_SIZE,
+                                       (dma_addr_t *) &mfd->cursor_buf_phys,
+                                       GFP_KERNEL);
+               if (!mfd->cursor_buf)
+                       mfd->cursor_update = 0;
+       }
+
+       if (mfd->lut_update) {
+               ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+               if (ret)
+                       printk(KERN_ERR "%s: fb_alloc_cmap() failed!\n",
+                                       __func__);
+       }
+
+       if (register_framebuffer(fbi) < 0) {
+               if (mfd->lut_update)
+                       fb_dealloc_cmap(&fbi->cmap);
+
+               if (mfd->cursor_buf)
+                       dma_free_coherent(NULL,
+                               MDP_CURSOR_SIZE,
+                               mfd->cursor_buf,
+                               (dma_addr_t) mfd->cursor_buf_phys);
+
+               mfd->op_enable = FALSE;
+               return -EPERM;
+       }
+
+       fbram += fix->smem_len;
+       fbram_phys += fix->smem_len;
+       fbram_size -= fix->smem_len;
+
+       MSM_FB_INFO
+           ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n",
+            mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len);
+
+#ifdef CONFIG_FB_MSM_LOGO
+       if (!load_565rle_image(INIT_IMAGE_FILE)) ;      /* Flip buffer */
+#endif
+       ret = 0;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       mfd->early_suspend.suspend = msmfb_early_suspend;
+       mfd->early_suspend.resume = msmfb_early_resume;
+       mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
+       register_early_suspend(&mfd->early_suspend);
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+       {
+               struct dentry *root;
+               struct dentry *sub_dir;
+               char sub_name[2];
+
+               root = msm_fb_get_debugfs_root();
+               if (root != NULL) {
+                       sub_name[0] = (char)(mfd->index + 0x30);
+                       sub_name[1] = '\0';
+                       sub_dir = debugfs_create_dir(sub_name, root);
+               } else {
+                       sub_dir = NULL;
+               }
+
+               mfd->sub_dir = sub_dir;
+
+               if (sub_dir) {
+                       msm_fb_debugfs_file_create(sub_dir, "op_enable",
+                                                  (u32 *) &mfd->op_enable);
+                       msm_fb_debugfs_file_create(sub_dir, "panel_power_on",
+                                                  (u32 *) &mfd->
+                                                  panel_power_on);
+                       msm_fb_debugfs_file_create(sub_dir, "ref_cnt",
+                                                  (u32 *) &mfd->ref_cnt);
+                       msm_fb_debugfs_file_create(sub_dir, "fb_imgType",
+                                                  (u32 *) &mfd->fb_imgType);
+                       msm_fb_debugfs_file_create(sub_dir,
+                                                  "sw_currently_refreshing",
+                                                  (u32 *) &mfd->
+                                                  sw_currently_refreshing);
+                       msm_fb_debugfs_file_create(sub_dir,
+                                                  "sw_refreshing_enable",
+                                                  (u32 *) &mfd->
+                                                  sw_refreshing_enable);
+
+                       msm_fb_debugfs_file_create(sub_dir, "xres",
+                                                  (u32 *) &mfd->panel_info.
+                                                  xres);
+                       msm_fb_debugfs_file_create(sub_dir, "yres",
+                                                  (u32 *) &mfd->panel_info.
+                                                  yres);
+                       msm_fb_debugfs_file_create(sub_dir, "bpp",
+                                                  (u32 *) &mfd->panel_info.
+                                                  bpp);
+                       msm_fb_debugfs_file_create(sub_dir, "type",
+                                                  (u32 *) &mfd->panel_info.
+                                                  type);
+                       msm_fb_debugfs_file_create(sub_dir, "wait_cycle",
+                                                  (u32 *) &mfd->panel_info.
+                                                  wait_cycle);
+                       msm_fb_debugfs_file_create(sub_dir, "pdest",
+                                                  (u32 *) &mfd->panel_info.
+                                                  pdest);
+                       msm_fb_debugfs_file_create(sub_dir, "backbuff",
+                                                  (u32 *) &mfd->panel_info.
+                                                  fb_num);
+                       msm_fb_debugfs_file_create(sub_dir, "clk_rate",
+                                                  (u32 *) &mfd->panel_info.
+                                                  clk_rate);
+                       msm_fb_debugfs_file_create(sub_dir, "frame_count",
+                                                  (u32 *) &mfd->panel_info.
+                                                  frame_count);
+
+
+                       switch (mfd->dest) {
+                       case DISPLAY_LCD:
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "vsync_enable",
+                               (u32 *)&mfd->panel_info.lcd.vsync_enable);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "refx100",
+                               (u32 *) &mfd->panel_info.lcd. refx100);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "v_back_porch",
+                               (u32 *) &mfd->panel_info.lcd.v_back_porch);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "v_front_porch",
+                               (u32 *) &mfd->panel_info.lcd.v_front_porch);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "v_pulse_width",
+                               (u32 *) &mfd->panel_info.lcd.v_pulse_width);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "hw_vsync_mode",
+                               (u32 *) &mfd->panel_info.lcd.hw_vsync_mode);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "vsync_notifier_period", (u32 *)
+                               &mfd->panel_info.lcd.vsync_notifier_period);
+                               break;
+
+                       case DISPLAY_LCDC:
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "h_back_porch",
+                               (u32 *) &mfd->panel_info.lcdc.h_back_porch);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "h_front_porch",
+                               (u32 *) &mfd->panel_info.lcdc.h_front_porch);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "h_pulse_width",
+                               (u32 *) &mfd->panel_info.lcdc.h_pulse_width);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "v_back_porch",
+                               (u32 *) &mfd->panel_info.lcdc.v_back_porch);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "v_front_porch",
+                               (u32 *) &mfd->panel_info.lcdc.v_front_porch);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "v_pulse_width",
+                               (u32 *) &mfd->panel_info.lcdc.v_pulse_width);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "border_clr",
+                               (u32 *) &mfd->panel_info.lcdc.border_clr);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "underflow_clr",
+                               (u32 *) &mfd->panel_info.lcdc.underflow_clr);
+                               msm_fb_debugfs_file_create(sub_dir,
+                               "hsync_skew",
+                               (u32 *) &mfd->panel_info.lcdc.hsync_skew);
+                               break;
+
+                       default:
+                               break;
+                       }
+               }
+       }
+#endif /* MSM_FB_ENABLE_DBGFS */
+
+       return ret;
+}
+
+static int msm_fb_open(struct fb_info *info, int user)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+       if (!mfd->ref_cnt) {
+               mdp_set_dma_pan_info(info, NULL, TRUE);
+
+               if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
+                       printk(KERN_ERR "msm_fb_open: can't turn on display!\n");
+                       return -1;
+               }
+       }
+
+       mfd->ref_cnt++;
+       return 0;
+}
+
+static int msm_fb_release(struct fb_info *info, int user)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       int ret = 0;
+
+       if (!mfd->ref_cnt) {
+               MSM_FB_INFO("msm_fb_release: try to close unopened fb %d!\n",
+                           mfd->index);
+               return -EINVAL;
+       }
+
+       mfd->ref_cnt--;
+
+       if (!mfd->ref_cnt) {
+               if ((ret =
+                    msm_fb_blank_sub(FB_BLANK_POWERDOWN, info,
+                                     mfd->op_enable)) != 0) {
+                       printk(KERN_ERR "msm_fb_release: can't turn off display!\n");
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+DECLARE_MUTEX(msm_fb_pan_sem);
+
+static int msm_fb_pan_display(struct fb_var_screeninfo *var,
+                             struct fb_info *info)
+{
+       struct mdp_dirty_region dirty;
+       struct mdp_dirty_region *dirtyPtr = NULL;
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+       if ((!mfd->op_enable) || (!mfd->panel_power_on))
+               return -EPERM;
+
+       if (var->xoffset > (info->var.xres_virtual - info->var.xres))
+               return -EINVAL;
+
+       if (var->yoffset > (info->var.yres_virtual - info->var.yres))
+               return -EINVAL;
+
+       if (info->fix.xpanstep)
+               info->var.xoffset =
+                   (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
+
+       if (info->fix.ypanstep)
+               info->var.yoffset =
+                   (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
+
+       /* "UPDT" */
+       if (var->reserved[0] == 0x54445055) {
+               dirty.xoffset = var->reserved[1] & 0xffff;
+               dirty.yoffset = (var->reserved[1] >> 16) & 0xffff;
+
+               if ((var->reserved[2] & 0xffff) <= dirty.xoffset)
+                       return -EINVAL;
+               if (((var->reserved[2] >> 16) & 0xffff) <= dirty.yoffset)
+                       return -EINVAL;
+
+               dirty.width = (var->reserved[2] & 0xffff) - dirty.xoffset;
+               dirty.height =
+                   ((var->reserved[2] >> 16) & 0xffff) - dirty.yoffset;
+               info->var.yoffset = var->yoffset;
+
+               if (dirty.xoffset < 0)
+                       return -EINVAL;
+
+               if (dirty.yoffset < 0)
+                       return -EINVAL;
+
+               if ((dirty.xoffset + dirty.width) > info->var.xres)
+                       return -EINVAL;
+
+               if ((dirty.yoffset + dirty.height) > info->var.yres)
+                       return -EINVAL;
+
+               if ((dirty.width <= 0) || (dirty.height <= 0))
+                       return -EINVAL;
+
+               dirtyPtr = &dirty;
+       }
+
+       /* Flip */
+       /* A constant value is used to indicate that we should change the DMA
+          output buffer instead of just panning */
+
+       if (var->reserved[0] == 0x466c6970) {
+               unsigned long length, address;
+               struct file *p_src_file;
+               struct mdp_img imgdata;
+               int bpp;
+
+               if (mfd->allow_set_offset) {
+                       imgdata.memory_id = var->reserved[1];
+                       imgdata.priv = var->reserved[2];
+
+                       /* If there is no memory ID then we want to reset back
+                          to the original fb visibility */
+                       if (var->reserved[1]) {
+                               if (var->reserved[4] == MDP_BLIT_SRC_GEM) {
+                                       panic("waaaaaaaaaaaaaah");
+                                       if ( /*get_gem_img(&imgdata,
+                                               (unsigned long *) &address,
+                                                &length)*/ -1 < 0) {
+                                               return -1;
+                                       }
+                               } else {
+                                       /*get_img(&imgdata, info, &address,
+                                                       &length, &p_src_file);*/
+                                       panic("waaaaaah");
+                               }
+                               mfd->ibuf.visible_swapped = TRUE;
+                       } else {
+                               /* Flip back to the original address
+                                  adjusted for xoffset and yoffset */
+
+                               bpp = info->var.bits_per_pixel / 8;
+                               address = (unsigned long) info->fix.smem_start;
+                               address += info->var.xoffset * bpp +
+                               info->var.yoffset * info->fix.line_length;
+
+                               mfd->ibuf.visible_swapped = FALSE;
+                       }
+
+                       mdp_set_offset_info(info, address,
+                               (var->activate == FB_ACTIVATE_VBL));
+
+                       mfd->dma_fnc(mfd);
+                       return 0;
+               } else
+                       return -EINVAL;
+       }
+
+       down(&msm_fb_pan_sem);
+       mdp_set_dma_pan_info(info, dirtyPtr,
+                            (var->activate == FB_ACTIVATE_VBL));
+       mdp_dma_pan_update(info);
+       up(&msm_fb_pan_sem);
+
+       ++mfd->panel_info.frame_count;
+       return 0;
+}
+
+static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+       if (var->rotate != FB_ROTATE_UR)
+               return -EINVAL;
+       if (var->grayscale != info->var.grayscale)
+               return -EINVAL;
+
+       switch (var->bits_per_pixel) {
+       case 16:
+               if ((var->green.offset != 5) ||
+                       !((var->blue.offset == 11)
+                               || (var->blue.offset == 0)) ||
+                       !((var->red.offset == 11)
+                               || (var->red.offset == 0)) ||
+                       (var->blue.length != 5) ||
+                       (var->green.length != 6) ||
+                       (var->red.length != 5) ||
+                       (var->blue.msb_right != 0) ||
+                       (var->green.msb_right != 0) ||
+                       (var->red.msb_right != 0) ||
+                       (var->transp.offset != 0) ||
+                       (var->transp.length != 0))
+                               return -EINVAL;
+               break;
+
+       case 24:
+               if ((var->blue.offset != 0) ||
+                       (var->green.offset != 8) ||
+                       (var->red.offset != 16) ||
+                       (var->blue.length != 8) ||
+                       (var->green.length != 8) ||
+                       (var->red.length != 8) ||
+                       (var->blue.msb_right != 0) ||
+                       (var->green.msb_right != 0) ||
+                       (var->red.msb_right != 0) ||
+                       !(((var->transp.offset == 0) &&
+                               (var->transp.length == 0)) ||
+                         ((var->transp.offset == 24) &&
+                               (var->transp.length == 8))))
+                               return -EINVAL;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0))
+               return -EINVAL;
+
+       if (info->fix.smem_len <
+               (var->xres_virtual*var->yres_virtual*(var->bits_per_pixel/8)))
+               return -EINVAL;
+
+       if ((var->xres == 0) || (var->yres == 0))
+               return -EINVAL;
+
+       if ((var->xres > mfd->panel_info.xres) ||
+               (var->yres > mfd->panel_info.yres))
+               return -EINVAL;
+
+       if (var->xoffset > (var->xres_virtual - var->xres))
+               return -EINVAL;
+
+       if (var->yoffset > (var->yres_virtual - var->yres))
+               return -EINVAL;
+
+       return 0;
+}
+
+static int msm_fb_set_par(struct fb_info *info)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       struct fb_var_screeninfo *var = &info->var;
+       int old_imgType;
+       int blank = 0;
+
+       old_imgType = mfd->fb_imgType;
+       switch (var->bits_per_pixel) {
+       case 16:
+               if (var->red.offset == 0)
+                       mfd->fb_imgType = MDP_BGR_565;
+               else
+                       mfd->fb_imgType = MDP_RGB_565;
+               break;
+
+       case 24:
+               if ((var->transp.offset == 0) && (var->transp.length == 0))
+                       mfd->fb_imgType = MDP_RGB_888;
+               else if ((var->transp.offset == 24) &&
+                               (var->transp.length == 8)) {
+                       mfd->fb_imgType = MDP_ARGB_8888;
+                       info->var.bits_per_pixel = 32;
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       if ((mfd->var_pixclock != var->pixclock) ||
+               (mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) ||
+                               (mfd->var_pixclock != var->pixclock) ||
+                               (mfd->var_xres != var->xres) ||
+                               (mfd->var_yres != var->yres)))) {
+               mfd->var_xres = var->xres;
+               mfd->var_yres = var->yres;
+               mfd->var_pixclock = var->pixclock;
+               blank = 1;
+       }
+
+       if (blank) {
+               msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
+               msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable);
+       }
+
+       return 0;
+}
+
+static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd)
+{
+       if (mfd->hw_refresh)
+               return -EPERM;
+
+       if (mfd->sw_currently_refreshing) {
+               down(&mfd->sem);
+               mfd->sw_currently_refreshing = FALSE;
+               up(&mfd->sem);
+
+               /* wait until the refresher finishes the last job */
+               wait_for_completion_killable(&mfd->refresher_comp);
+       }
+
+       return 0;
+}
+
+int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd)
+{
+       boolean do_refresh;
+
+       if (mfd->hw_refresh)
+               return -EPERM;
+
+       down(&mfd->sem);
+       if ((!mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
+               do_refresh = TRUE;
+               mfd->sw_currently_refreshing = TRUE;
+       } else {
+               do_refresh = FALSE;
+       }
+       up(&mfd->sem);
+
+       if (do_refresh)
+               mdp_refresh_screen((unsigned long)mfd);
+
+       return 0;
+}
+
+void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file)
+{
+#ifdef CONFIG_ANDROID_PMEM
+       if (p_src_file)
+               put_pmem_file(p_src_file);
+       if (p_dst_file)
+               put_pmem_file(p_dst_file);
+#endif
+}
+
+int mdp_blit(struct fb_info *info, struct mdp_blit_req *req)
+{
+       int ret;
+       struct file *p_src_file = 0, *p_dst_file = 0;
+       if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) {
+               printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
+               return -EINVAL;
+       }
+       if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0))
+               return 0;
+
+       ret = mdp_ppp_blit(info, req, &p_src_file, &p_dst_file);
+       mdp_ppp_put_img(p_src_file, p_dst_file);
+       return ret;
+}
+
+typedef void (*msm_dma_barrier_function_pointer) (void *, size_t);
+
+static inline void msm_fb_dma_barrier_for_rect(struct fb_info *info,
+                       struct mdp_img *img, struct mdp_rect *rect,
+                       msm_dma_barrier_function_pointer dma_barrier_fp
+                       )
+{
+       /*
+        * Compute the start and end addresses of the rectangles.
+        * NOTE: As currently implemented, the data between
+        *       the end of one row and the start of the next is
+        *       included in the address range rather than
+        *       doing multiple calls for each row.
+        */
+
+       char * const pmem_start = info->screen_base;
+/*     int bytes_per_pixel = mdp_get_bytes_per_pixel(img->format);
+       unsigned long start = (unsigned long)pmem_start + img->offset +
+               (img->width * rect->y + rect->x) * bytes_per_pixel;
+       size_t size  = ((rect->h - 1) * img->width + rect->w) * bytes_per_pixel;
+       (*dma_barrier_fp) ((void *) start, size);
+*/
+       panic("waaaaah");
+}
+
+static inline void msm_dma_nc_pre(void)
+{
+       dmb();
+}
+static inline void msm_dma_wt_pre(void)
+{
+       dmb();
+}
+static inline void msm_dma_todevice_wb_pre(void *start, size_t size)
+{
+       #warning this
+//     dma_cache_pre_ops(start, size, DMA_TO_DEVICE);
+}
+
+static inline void msm_dma_fromdevice_wb_pre(void *start, size_t size)
+{
+       #warning this
+//     dma_cache_pre_ops(start, size, DMA_FROM_DEVICE);
+}
+
+static inline void msm_dma_nc_post(void)
+{
+       dmb();
+}
+
+static inline void msm_dma_fromdevice_wt_post(void *start, size_t size)
+{
+       #warning this
+//     dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
+}
+
+static inline void msm_dma_todevice_wb_post(void *start, size_t size)
+{
+       #warning this
+//     dma_cache_post_ops(start, size, DMA_TO_DEVICE);
+}
+
+static inline void msm_dma_fromdevice_wb_post(void *start, size_t size)
+{
+       #warning this
+//     dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
+}
+
+/*
+ * Do the write barriers required to guarantee data is committed to RAM
+ * (from CPU cache or internal buffers) before a DMA operation starts.
+ * NOTE: As currently implemented, the data between
+ *       the end of one row and the start of the next is
+ *       included in the address range rather than
+ *       doing multiple calls for each row.
+*/
+static void msm_fb_ensure_memory_coherency_before_dma(struct fb_info *info,
+               struct mdp_blit_req *req_list,
+               int req_list_count)
+{
+#ifdef CONFIG_ARCH_QSD8X50
+       int i;
+
+       /*
+        * Normally, do the requested barriers for each address
+        * range that corresponds to a rectangle.
+        *
+        * But if at least one write barrier is requested for data
+        * going to or from the device but no address range is
+        * needed for that barrier, then do the barrier, but do it
+        * only once, no matter how many requests there are.
+        */
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       switch (mfd->mdp_fb_page_protection)    {
+       default:
+       case MDP_FB_PAGE_PROTECTION_NONCACHED:
+       case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+               /*
+                * The following barrier is only done at most once,
+                * since further calls would be redundant.
+                */
+               for (i = 0; i < req_list_count; i++) {
+                       if (!(req_list[i].flags
+                               & MDP_NO_DMA_BARRIER_START)) {
+                               msm_dma_nc_pre();
+                               break;
+                       }
+               }
+               break;
+
+       case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+               /*
+                * The following barrier is only done at most once,
+                * since further calls would be redundant.
+                */
+               for (i = 0; i < req_list_count; i++) {
+                       if (!(req_list[i].flags
+                               & MDP_NO_DMA_BARRIER_START)) {
+                               msm_dma_wt_pre();
+                               break;
+                       }
+               }
+               break;
+
+       case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+       case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+               for (i = 0; i < req_list_count; i++) {
+                       if (!(req_list[i].flags &
+                                       MDP_NO_DMA_BARRIER_START)) {
+
+                               msm_fb_dma_barrier_for_rect(info,
+                                               &(req_list[i].src),
+                                               &(req_list[i].src_rect),
+                                               msm_dma_todevice_wb_pre
+                                               );
+
+                               msm_fb_dma_barrier_for_rect(info,
+                                               &(req_list[i].dst),
+                                               &(req_list[i].dst_rect),
+                                               msm_dma_todevice_wb_pre
+                                               );
+                       }
+               }
+               break;
+       }
+#else
+       dmb();
+#endif
+}
+
+
+/*
+ * Do the write barriers required to guarantee data will be re-read from RAM by
+ * the CPU after a DMA operation ends.
+ * NOTE: As currently implemented, the data between
+ *       the end of one row and the start of the next is
+ *       included in the address range rather than
+ *       doing multiple calls for each row.
+*/
+static void msm_fb_ensure_memory_coherency_after_dma(struct fb_info *info,
+               struct mdp_blit_req *req_list,
+               int req_list_count)
+{
+#ifdef CONFIG_ARCH_QSD8X50
+       int i;
+
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       switch (mfd->mdp_fb_page_protection)    {
+       default:
+       case MDP_FB_PAGE_PROTECTION_NONCACHED:
+       case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+               /*
+                * The following barrier is only done at most once,
+                * since further calls would be redundant.
+                */
+               for (i = 0; i < req_list_count; i++) {
+                       if (!(req_list[i].flags
+                               & MDP_NO_DMA_BARRIER_END)) {
+                               msm_dma_nc_post();
+                               break;
+                       }
+               }
+               break;
+
+       case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+               for (i = 0; i < req_list_count; i++) {
+                       if (!(req_list[i].flags &
+                                       MDP_NO_DMA_BARRIER_END)) {
+
+                               msm_fb_dma_barrier_for_rect(info,
+                                               &(req_list[i].dst),
+                                               &(req_list[i].dst_rect),
+                                               msm_dma_fromdevice_wt_post
+                                               );
+                       }
+               }
+               break;
+       case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+       case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+               for (i = 0; i < req_list_count; i++) {
+                       if (!(req_list[i].flags &
+                                       MDP_NO_DMA_BARRIER_END)) {
+
+                               msm_fb_dma_barrier_for_rect(info,
+                                               &(req_list[i].dst),
+                                               &(req_list[i].dst_rect),
+                                               msm_dma_fromdevice_wb_post
+                                               );
+                       }
+               }
+               break;
+       }
+#else
+       dmb();
+#endif
+}
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info,
+       struct mdp_blit_req *req_list, int req_list_count)
+{
+       BUG_ON(!info);
+
+       /*
+        * Ensure that CPU cache and other internal CPU state is
+        * updated to reflect any change in memory modified by MDP blit
+        * DMA.
+        */
+       msm_fb_ensure_memory_coherency_after_dma(info,
+                       req_list, req_list_count);
+}
+
+static int msmfb_async_blit(struct fb_info *info, void __user *p)
+{
+       /*
+        * CAUTION: The names of the struct types intentionally *DON'T* match
+        * the names of the variables declared -- they appear to be swapped.
+        * Read the code carefully and you should see that the variable names
+        * make sense.
+        */
+       const int MAX_LIST_WINDOW = 16;
+       struct mdp_blit_req req_list[MAX_LIST_WINDOW];
+       struct mdp_blit_req_list req_list_header;
+
+       int count, i, req_list_count;
+
+       /* Get the count size for the total BLIT request. */
+       if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
+               return -EFAULT;
+       p += sizeof(req_list_header);
+       count = req_list_header.count;
+       while (count > 0) {
+               /*
+                * Access the requests through a narrow window to decrease copy
+                * overhead and make larger requests accessible to the
+                * coherency management code.
+                * NOTE: The window size is intended to be larger than the
+                *       typical request size, but not require more than 2
+                *       kbytes of stack storage.
+                */
+               req_list_count = count;
+               if (req_list_count > MAX_LIST_WINDOW)
+                       req_list_count = MAX_LIST_WINDOW;
+               if (copy_from_user(&req_list, p,
+                               sizeof(struct mdp_blit_req)*req_list_count))
+                       return -EFAULT;
+
+               /*
+                * Ensure that any data CPU may have previously written to
+                * internal state (but not yet committed to memory) is
+                * guaranteed to be committed to memory now.
+                */
+               msm_fb_ensure_memory_coherency_before_dma(info,
+                               req_list, req_list_count);
+
+               /*
+                * Do the blit DMA, if required -- returning early only if
+                * there is a failure.
+                */
+               for (i = 0; i < req_list_count; i++) {
+                       if (!(req_list[i].flags & MDP_NO_BLIT)) {
+                               int ret = 0;
+                               struct mdp_ppp_djob *job = NULL;
+
+                               if (unlikely(req_list[i].src_rect.h == 0 ||
+                                       req_list[i].src_rect.w == 0)) {
+                                       MSM_FB_ERR("mpd_ppp: "
+                                               "src img of zero size!\n");
+                                       return -EINVAL;
+                               }
+
+                               if (unlikely(req_list[i].dst_rect.h == 0 ||
+                                       req_list[i].dst_rect.w == 0))
+                                       continue;
+
+                               /* create a new display job */
+                               job = mdp_ppp_new_djob();
+                               if (unlikely(!job))
+                                       return -ENOMEM;
+
+                               job->info = info;
+                               memcpy(&job->req, &req_list[i],
+                                       sizeof(struct mdp_blit_req));
+
+                               /* Do the actual blit. */
+                               ret = mdp_ppp_blit(info, &job->req,
+                                       &job->p_src_file, &job->p_dst_file);
+
+                               /*
+                                * Note that early returns don't guarantee
+                                * memory coherency.
+                                */
+                               if (ret || mdp_ppp_get_ret_code()) {
+                                       mdp_ppp_clear_curr_djob();
+                                       return ret;
+                               }
+                       }
+               }
+
+               /* Go to next window of requests. */
+               count -= req_list_count;
+               p += sizeof(struct mdp_blit_req)*req_list_count;
+       }
+       return 0;
+}
+#else
+
+/*
+ * NOTE: The userspace issues blit operations in a sequence, the sequence
+ * start with a operation marked START and ends in an operation marked
+ * END. It is guranteed by the userspace that all the blit operations
+ * between START and END are only within the regions of areas designated
+ * by the START and END operations and that the userspace doesnt modify
+ * those areas. Hence it would be enough to perform barrier/cache operations
+ * only on the START and END operations.
+ */
+static int msmfb_blit(struct fb_info *info, void __user *p)
+{
+       /*
+        * CAUTION: The names of the struct types intentionally *DON'T* match
+        * the names of the variables declared -- they appear to be swapped.
+        * Read the code carefully and you should see that the variable names
+        * make sense.
+        */
+       const int MAX_LIST_WINDOW = 16;
+       struct mdp_blit_req req_list[MAX_LIST_WINDOW];
+       struct mdp_blit_req_list req_list_header;
+
+       int count, i, req_list_count;
+
+       /* Get the count size for the total BLIT request. */
+       if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
+               return -EFAULT;
+       p += sizeof(req_list_header);
+       count = req_list_header.count;
+       while (count > 0) {
+               /*
+                * Access the requests through a narrow window to decrease copy
+                * overhead and make larger requests accessible to the
+                * coherency management code.
+                * NOTE: The window size is intended to be larger than the
+                *       typical request size, but not require more than 2
+                *       kbytes of stack storage.
+                */
+               req_list_count = count;
+               if (req_list_count > MAX_LIST_WINDOW)
+                       req_list_count = MAX_LIST_WINDOW;
+               if (copy_from_user(&req_list, p,
+                               sizeof(struct mdp_blit_req)*req_list_count))
+                       return -EFAULT;
+
+               /*
+                * Ensure that any data CPU may have previously written to
+                * internal state (but not yet committed to memory) is
+                * guaranteed to be committed to memory now.
+                */
+               msm_fb_ensure_memory_coherency_before_dma(info,
+                               req_list, req_list_count);
+
+               /*
+                * Do the blit DMA, if required -- returning early only if
+                * there is a failure.
+                */
+               for (i = 0; i < req_list_count; i++) {
+                       if (!(req_list[i].flags & MDP_NO_BLIT)) {
+                               /* Do the actual blit. */
+                               int ret = mdp_blit(info, &(req_list[i]));
+
+                               /*
+                                * Note that early returns don't guarantee
+                                * memory coherency.
+                                */
+                               if (ret)
+                                       return ret;
+                       }
+               }
+
+               /*
+                * Ensure that CPU cache and other internal CPU state is
+                * updated to reflect any change in memory modified by MDP blit
+                * DMA.
+                */
+               msm_fb_ensure_memory_coherency_after_dma(info,
+                               req_list,
+                               req_list_count);
+
+               /* Go to next window of requests. */
+               count -= req_list_count;
+               p += sizeof(struct mdp_blit_req)*req_list_count;
+       }
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_FB_MSM_OVERLAY
+static int msmfb_overlay_get(struct fb_info *info, void __user *p)
+{
+       struct mdp_overlay req;
+       int ret;
+
+       if (copy_from_user(&req, p, sizeof(req)))
+               return -EFAULT;
+
+       ret = mdp4_overlay_get(info, &req);
+       if (ret) {
+               printk(KERN_ERR "%s: ioctl failed \n",
+                       __func__);
+               return ret;
+       }
+       if (copy_to_user(p, &req, sizeof(req))) {
+               printk(KERN_ERR "%s: copy2user failed \n",
+                       __func__);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+static int msmfb_overlay_set(struct fb_info *info, void __user *p)
+{
+       struct mdp_overlay req;
+       int ret;
+
+       if (copy_from_user(&req, p, sizeof(req)))
+               return -EFAULT;
+
+       ret = mdp4_overlay_set(info, &req);
+       if (ret) {
+               printk(KERN_ERR "%s:ioctl failed \n",
+                       __func__);
+               return ret;
+       }
+
+       if (copy_to_user(p, &req, sizeof(req))) {
+               printk(KERN_ERR "%s: copy2user failed \n",
+                       __func__);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+static int msmfb_overlay_unset(struct fb_info *info, unsigned long *argp)
+{
+       int     ret, ndx;
+
+       ret = copy_from_user(&ndx, argp, sizeof(ndx));
+       if (ret) {
+               printk(KERN_ERR "%s:msmfb_overlay_unset ioctl failed \n",
+                       __func__);
+               return ret;
+       }
+
+       return mdp4_overlay_unset(info, ndx);
+}
+
+static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp)
+{
+       int     ret;
+       struct msmfb_overlay_data req;
+       struct file *p_src_file = 0;
+
+       ret = copy_from_user(&req, argp, sizeof(req));
+       if (ret) {
+               printk(KERN_ERR "%s:msmfb_overlay_play ioctl failed \n",
+                       __func__);
+               return ret;
+       }
+
+       ret = mdp4_overlay_play(info, &req, &p_src_file);
+
+       if (p_src_file)
+               put_pmem_file(p_src_file);
+
+       return ret;
+}
+
+#endif
+
+DECLARE_MUTEX(msm_fb_ioctl_ppp_sem);
+DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
+DEFINE_MUTEX(msm_fb_ioctl_hist_sem);
+
+/* Set color conversion matrix from user space */
+
+#ifndef CONFIG_FB_MSM_MDP40
+static void msmfb_set_color_conv(struct mdp_ccs *p)
+{
+       int i;
+
+       if (p->direction == MDP_CCS_RGB2YUV) {
+               /* MDP cmd block enable */
+               mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+               /* RGB->YUV primary forward matrix */
+               for (i = 0; i < MDP_CCS_SIZE; i++)
+                       writel(p->ccs[i], MDP_CSC_PFMVn(i));
+
+               #ifdef CONFIG_FB_MSM_MDP31
+               for (i = 0; i < MDP_BV_SIZE; i++)
+                       writel(p->bv[i], MDP_CSC_POST_BV2n(i));
+               #endif
+
+               /* MDP cmd block disable */
+               mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+       } else {
+               /* MDP cmd block enable */
+               mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+               /* YUV->RGB primary reverse matrix */
+               for (i = 0; i < MDP_CCS_SIZE; i++)
+                       writel(p->ccs[i], MDP_CSC_PRMVn(i));
+               for (i = 0; i < MDP_BV_SIZE; i++)
+                       writel(p->bv[i], MDP_CSC_PRE_BV1n(i));
+
+               /* MDP cmd block disable */
+               mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+       }
+}
+#endif
+
+
+static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
+                       unsigned long arg)
+{
+       struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+       void __user *argp = (void __user *)arg;
+       struct fb_cursor cursor;
+       struct fb_cmap cmap;
+       struct mdp_histogram hist;
+#ifndef CONFIG_FB_MSM_MDP40
+       struct mdp_ccs ccs_matrix;
+#endif
+       struct mdp_page_protection fb_page_protection;
+       int ret = 0;
+
+       if (!mfd->op_enable)
+               return -EPERM;
+
+       switch (cmd) {
+#ifdef CONFIG_FB_MSM_OVERLAY
+       case MSMFB_OVERLAY_GET:
+               down(&msm_fb_ioctl_ppp_sem);
+               ret = msmfb_overlay_get(info, argp);
+               up(&msm_fb_ioctl_ppp_sem);
+               break;
+       case MSMFB_OVERLAY_SET:
+               down(&msm_fb_ioctl_ppp_sem);
+               ret = msmfb_overlay_set(info, argp);
+               up(&msm_fb_ioctl_ppp_sem);
+               break;
+       case MSMFB_OVERLAY_UNSET:
+               down(&msm_fb_ioctl_ppp_sem);
+               ret = msmfb_overlay_unset(info, argp);
+               up(&msm_fb_ioctl_ppp_sem);
+               break;
+       case MSMFB_OVERLAY_PLAY:
+               down(&msm_fb_ioctl_ppp_sem);
+               ret = msmfb_overlay_play(info, argp);
+               up(&msm_fb_ioctl_ppp_sem);
+               break;
+#endif
+       case MSMFB_BLIT:
+               down(&msm_fb_ioctl_ppp_sem);
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+               ret = msmfb_async_blit(info, argp);
+               mdp_ppp_wait(); /* Wait for all blits to be finished. */
+#else
+               ret = msmfb_blit(info, argp);
+#endif
+               up(&msm_fb_ioctl_ppp_sem);
+
+               break;
+
+       /* Ioctl for setting ccs matrix from user space */
+       case MSMFB_SET_CCS_MATRIX:
+#ifndef CONFIG_FB_MSM_MDP40
+               ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix));
+               if (ret) {
+                       printk(KERN_ERR
+                               "%s:MSMFB_SET_CCS_MATRIX ioctl failed \n",
+                               __func__);
+                       return ret;
+               }
+
+               down(&msm_fb_ioctl_ppp_sem);
+               if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
+                       mdp_ccs_rgb2yuv = ccs_matrix;
+               else
+                       mdp_ccs_yuv2rgb = ccs_matrix;
+
+               msmfb_set_color_conv(&ccs_matrix) ;
+               up(&msm_fb_ioctl_ppp_sem);
+#else
+               ret = -EINVAL;
+#endif
+
+               break;
+
+       /* Ioctl for getting ccs matrix to user space */
+       case MSMFB_GET_CCS_MATRIX:
+#ifndef CONFIG_FB_MSM_MDP40
+               ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)) ;
+               if (ret) {
+                       printk(KERN_ERR
+                               "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
+                                __func__);
+                       return ret;
+               }
+
+               down(&msm_fb_ioctl_ppp_sem);
+               if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
+                       ccs_matrix = mdp_ccs_rgb2yuv;
+                else
+                       ccs_matrix =  mdp_ccs_yuv2rgb;
+
+               ret = copy_to_user(argp, &ccs_matrix, sizeof(ccs_matrix));
+
+               if (ret)        {
+                       printk(KERN_ERR
+                               "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
+                                __func__);
+                       return ret ;
+               }
+               up(&msm_fb_ioctl_ppp_sem);
+#else
+               ret = -EINVAL;
+#endif
+
+               break;
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+       case MSMFB_ASYNC_BLIT:
+               down(&msm_fb_ioctl_ppp_sem);
+               ret = msmfb_async_blit(info, argp);
+               up(&msm_fb_ioctl_ppp_sem);
+               break;
+
+       case MSMFB_BLIT_FLUSH:
+               down(&msm_fb_ioctl_ppp_sem);
+               mdp_ppp_wait();
+               up(&msm_fb_ioctl_ppp_sem);
+               break;
+#endif
+
+       case MSMFB_GRP_DISP:
+#ifdef CONFIG_FB_MSM_MDP22
+               {
+                       unsigned long grp_id;
+
+                       ret = copy_from_user(&grp_id, argp, sizeof(grp_id));
+                       if (ret)
+                               return ret;
+
+                       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+                       writel(grp_id, MDP_FULL_BYPASS_WORD43);
+                       mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
+                                     FALSE);
+                       break;
+               }
+#else
+               return -EFAULT;
+#endif
+       case MSMFB_SUSPEND_SW_REFRESHER:
+               if (!mfd->panel_power_on)
+                       return -EPERM;
+
+               mfd->sw_refreshing_enable = FALSE;
+               ret = msm_fb_stop_sw_refresher(mfd);
+               break;
+
+       case MSMFB_RESUME_SW_REFRESHER:
+               if (!mfd->panel_power_on)
+                       return -EPERM;
+
+               mfd->sw_refreshing_enable = TRUE;
+               ret = msm_fb_resume_sw_refresher(mfd);
+               break;
+
+       case MSMFB_CURSOR:
+               ret = copy_from_user(&cursor, argp, sizeof(cursor));
+               if (ret)
+                       return ret;
+
+               ret = msm_fb_cursor(info, &cursor);
+               break;
+
+       case MSMFB_SET_LUT:
+               ret = copy_from_user(&cmap, argp, sizeof(cmap));
+               if (ret)
+                       return ret;
+
+               mutex_lock(&msm_fb_ioctl_lut_sem);
+               ret = msm_fb_set_lut(&cmap, info);
+               mutex_unlock(&msm_fb_ioctl_lut_sem);
+               break;
+
+       case MSMFB_HISTOGRAM:
+               if (!mfd->do_histogram)
+                       return -ENODEV;
+
+               ret = copy_from_user(&hist, argp, sizeof(hist));
+               if (ret)
+                       return ret;
+
+               mutex_lock(&msm_fb_ioctl_hist_sem);
+               ret = mfd->do_histogram(info, &hist);
+               mutex_unlock(&msm_fb_ioctl_hist_sem);
+               break;
+
+       case MSMFB_GET_PAGE_PROTECTION:
+               fb_page_protection.page_protection
+                       = mfd->mdp_fb_page_protection;
+               ret = copy_to_user(argp, &fb_page_protection,
+                               sizeof(fb_page_protection));
+               if (ret)
+                               return ret;
+               break;
+
+       case MSMFB_SET_PAGE_PROTECTION:
+#ifdef CONFIG_ARCH_QSD8X50
+               ret = copy_from_user(&fb_page_protection, argp,
+                               sizeof(fb_page_protection));
+               if (ret)
+                               return ret;
+
+               /* Validate the proposed page protection settings. */
+               switch (fb_page_protection.page_protection)     {
+               case MDP_FB_PAGE_PROTECTION_NONCACHED:
+               case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+               case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+               /* Write-back cache (read allocate)  */
+               case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+               /* Write-back cache (write allocate) */
+               case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+                       mfd->mdp_fb_page_protection =
+                               fb_page_protection.page_protection;
+                       break;
+               default:
+                       ret = -EINVAL;
+                       break;
+               }
+#else
+               /*
+                * Don't allow caching until 7k DMA cache operations are
+                * available.
+                */
+               ret = -EINVAL;
+#endif
+               break;
+
+       default:
+               MSM_FB_INFO("MDP: unknown ioctl (cmd=%d) received!\n", cmd);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int msm_fb_register_driver(void)
+{
+       return platform_driver_register(&msm_fb_driver);
+}
+
+void msm_fb_add_device(struct platform_device *pdev)
+{
+       struct msm_fb_panel_data *pdata;
+       struct platform_device *this_dev = NULL;
+       struct fb_info *fbi;
+       struct msm_fb_data_type *mfd = NULL;
+       u32 type, id, fb_num;
+
+       if (!pdev)
+               return;
+       id = pdev->id;
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata)
+               return;
+       type = pdata->panel_info.type;
+       fb_num = pdata->panel_info.fb_num;
+
+       if (fb_num <= 0)
+               return;
+
+       if (fbi_list_index >= MAX_FBI_LIST) {
+               printk(KERN_ERR "msm_fb: no more framebuffer info list!\n");
+               return;
+       }
+       /*
+        * alloc panel device data
+        */
+       this_dev = msm_fb_device_alloc(pdata, type, id);
+
+       if (!this_dev) {
+               printk(KERN_ERR
+               "%s: msm_fb_device_alloc failed!\n", __func__);
+               return;
+       }
+
+       /*
+        * alloc framebuffer info + par data
+        */
+       fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL);
+       if (fbi == NULL) {
+               platform_device_put(this_dev);
+               printk(KERN_ERR "msm_fb: can't alloca framebuffer info data!\n");
+               return;
+       }
+
+       mfd = (struct msm_fb_data_type *)fbi->par;
+       mfd->key = MFD_KEY;
+       mfd->fbi = fbi;
+       mfd->panel.type = type;
+       mfd->panel.id = id;
+       mfd->fb_page = fb_num;
+       mfd->index = fbi_list_index;
+       mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
+
+       /* link to the latest pdev */
+       mfd->pdev = this_dev;
+
+       mfd_list[mfd_list_index++] = mfd;
+       fbi_list[fbi_list_index++] = fbi;
+
+       /*
+        * set driver data
+        */
+       platform_set_drvdata(this_dev, mfd);
+
+       if (platform_device_add(this_dev)) {
+               printk(KERN_ERR "msm_fb: platform_device_add failed!\n");
+               platform_device_put(this_dev);
+               framebuffer_release(fbi);
+               fbi_list_index--;
+               return;
+       }
+}
+EXPORT_SYMBOL(msm_fb_add_device);
+
+int __init msm_fb_init(void)
+{
+       int rc = -ENODEV;
+
+       if (msm_fb_register_driver())
+               return rc;
+
+#ifdef MSM_FB_ENABLE_DBGFS
+       {
+               struct dentry *root;
+
+               if ((root = msm_fb_get_debugfs_root()) != NULL) {
+                       msm_fb_debugfs_file_create(root,
+                                                  "msm_fb_msg_printing_level",
+                                                  (u32 *) &msm_fb_msg_level);
+                       msm_fb_debugfs_file_create(root,
+                                                  "mddi_msg_printing_level",
+                                                  (u32 *) &mddi_msg_level);
+                       msm_fb_debugfs_file_create(root, "msm_fb_debug_enabled",
+                                                  (u32 *) &msm_fb_debug_enabled);
+               }
+       }
+#endif
+
+       return 0;
+}
+
+module_init(msm_fb_init);
diff --git a/drivers/staging/msm/msm_fb.h b/drivers/staging/msm/msm_fb.h
new file mode 100644 (file)
index 0000000..f939138
--- /dev/null
@@ -0,0 +1,174 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MSM_FB_H
+#define MSM_FB_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <mach/board.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/memory.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/hrtimer.h>
+
+#include <linux/fb.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include "msm_fb_panel.h"
+#include "mdp.h"
+
+#define MSM_FB_DEFAULT_PAGE_SIZE 2
+#define MFD_KEY  0x11161126
+#define MSM_FB_MAX_DEV_LIST 32
+
+struct disp_info_type_suspend {
+       boolean op_enable;
+       boolean sw_refreshing_enable;
+       boolean panel_power_on;
+};
+
+struct msm_fb_data_type {
+       __u32 key;
+       __u32 index;
+       __u32 ref_cnt;
+       __u32 fb_page;
+
+       panel_id_type panel;
+       struct msm_panel_info panel_info;
+
+       DISP_TARGET dest;
+       struct fb_info *fbi;
+
+       boolean op_enable;
+       uint32 fb_imgType;
+       boolean sw_currently_refreshing;
+       boolean sw_refreshing_enable;
+       boolean hw_refresh;
+
+       MDPIBUF ibuf;
+       boolean ibuf_flushed;
+       struct timer_list refresh_timer;
+       struct completion refresher_comp;
+
+       boolean pan_waiting;
+       struct completion pan_comp;
+
+       /* vsync */
+       boolean use_mdp_vsync;
+       __u32 vsync_gpio;
+       __u32 total_lcd_lines;
+       __u32 total_porch_lines;
+       __u32 lcd_ref_usec_time;
+       __u32 refresh_timer_duration;
+
+       struct hrtimer dma_hrtimer;
+
+       boolean panel_power_on;
+       struct work_struct dma_update_worker;
+       struct semaphore sem;
+
+       struct timer_list vsync_resync_timer;
+       boolean vsync_handler_pending;
+       struct work_struct vsync_resync_worker;
+
+       ktime_t last_vsync_timetick;
+
+       __u32 *vsync_width_boundary;
+
+       unsigned int pmem_id;
+       struct disp_info_type_suspend suspend;
+
+       __u32 channel_irq;
+
+       struct mdp_dma_data *dma;
+       void (*dma_fnc) (struct msm_fb_data_type *mfd);
+       int (*cursor_update) (struct fb_info *info,
+                             struct fb_cursor *cursor);
+       int (*lut_update) (struct fb_info *info,
+                             struct fb_cmap *cmap);
+       int (*do_histogram) (struct fb_info *info,
+                             struct mdp_histogram *hist);
+       void *cursor_buf;
+       void *cursor_buf_phys;
+
+       void *cmd_port;
+       void *data_port;
+       void *data_port_phys;
+
+       __u32 bl_level;
+
+       struct platform_device *pdev;
+
+       __u32 var_xres;
+       __u32 var_yres;
+       __u32 var_pixclock;
+
+#ifdef MSM_FB_ENABLE_DBGFS
+       struct dentry *sub_dir;
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       struct early_suspend early_suspend;
+       struct early_suspend mddi_early_suspend;
+       struct early_suspend mddi_ext_early_suspend;
+#endif
+       u32 mdp_fb_page_protection;
+       int allow_set_offset;
+};
+
+struct dentry *msm_fb_get_debugfs_root(void);
+void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
+                               u32 *var);
+void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl,
+                               u32 save);
+
+void msm_fb_add_device(struct platform_device *pdev);
+
+int msm_fb_detect_client(const char *name);
+
+#ifdef CONFIG_FB_BACKLIGHT
+void msm_fb_config_backlight(struct msm_fb_data_type *mfd);
+#endif
+
+#endif /* MSM_FB_H */
diff --git a/drivers/staging/msm/msm_fb_bl.c b/drivers/staging/msm/msm_fb_bl.c
new file mode 100644 (file)
index 0000000..033fc94
--- /dev/null
@@ -0,0 +1,79 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/backlight.h>
+
+#include "msm_fb.h"
+
+static int msm_fb_bl_get_brightness(struct backlight_device *pbd)
+{
+       return pbd->props.brightness;
+}
+
+static int msm_fb_bl_update_status(struct backlight_device *pbd)
+{
+       struct msm_fb_data_type *mfd = bl_get_data(pbd);
+       __u32 bl_lvl;
+
+       bl_lvl = pbd->props.brightness;
+       bl_lvl = mfd->fbi->bl_curve[bl_lvl];
+       msm_fb_set_backlight(mfd, bl_lvl, 1);
+       return 0;
+}
+
+static struct backlight_ops msm_fb_bl_ops = {
+       .get_brightness = msm_fb_bl_get_brightness,
+       .update_status = msm_fb_bl_update_status,
+};
+
+void msm_fb_config_backlight(struct msm_fb_data_type *mfd)
+{
+       struct msm_fb_panel_data *pdata;
+       struct backlight_device *pbd;
+       struct fb_info *fbi;
+       char name[16];
+
+       fbi = mfd->fbi;
+       pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+       if ((pdata) && (pdata->set_backlight)) {
+               snprintf(name, sizeof(name), "msmfb_bl%d", mfd->index);
+               pbd =
+                   backlight_device_register(name, fbi->dev, mfd,
+                                             &msm_fb_bl_ops);
+               if (!IS_ERR(pbd)) {
+                       fbi->bl_dev = pbd;
+                       fb_bl_default_curve(fbi,
+                                           0,
+                                           mfd->panel_info.bl_min,
+                                           mfd->panel_info.bl_max);
+                       pbd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+                       pbd->props.brightness = FB_BACKLIGHT_LEVELS - 1;
+                       backlight_update_status(pbd);
+               } else {
+                       fbi->bl_dev = NULL;
+                       printk(KERN_ERR "msm_fb: backlight_device_register failed!\n");
+               }
+       }
+}
diff --git a/drivers/staging/msm/msm_fb_def.h b/drivers/staging/msm/msm_fb_def.h
new file mode 100644 (file)
index 0000000..6de4409
--- /dev/null
@@ -0,0 +1,201 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MSM_FB_DEF_H
+#define MSM_FB_DEF_H
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include "msm_mdp.h"
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+#include <linux/console.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/fb.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/platform_device.h>
+
+typedef s64 int64;
+typedef s32 int32;
+typedef s16 int16;
+typedef s8 int8;
+
+typedef u64 uint64;
+typedef u32 uint32;
+typedef u16 uint16;
+typedef u8 uint8;
+
+typedef s32 int4;
+typedef s16 int2;
+typedef s8 int1;
+
+typedef u32 uint4;
+typedef u16 uint2;
+typedef u8 uint1;
+
+typedef u32 dword;
+typedef u16 word;
+typedef u8 byte;
+
+typedef unsigned int boolean;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define MSM_FB_ENABLE_DBGFS
+#define FEATURE_MDDI
+
+#define outp32(addr, val) writel(val, addr)
+#define outp16(addr, val) writew(val, addr)
+#define outp8(addr, val) writeb(val, addr)
+#define outp(addr, val) outp32(addr, val)
+
+#ifndef MAX
+#define  MAX( x, y ) (((x) > (y)) ? (x) : (y))
+#endif
+
+#ifndef MIN
+#define  MIN( x, y ) (((x) < (y)) ? (x) : (y))
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#define inp32(addr) readl(addr)
+#define inp16(addr) readw(addr)
+#define inp8(addr) readb(addr)
+#define inp(addr) inp32(addr)
+
+#define inpw(port)             readw(port)
+#define outpw(port, val)       writew(val, port)
+#define inpdw(port)            readl(port)
+#define outpdw(port, val)      writel(val, port)
+
+
+#define clk_busy_wait(x) msleep_interruptible((x)/1000)
+
+#define memory_barrier()
+
+#define assert(expr) \
+       if(!(expr)) { \
+               printk(KERN_ERR "msm_fb: assertion failed! %s,%s,%s,line=%d\n",\
+                       #expr, __FILE__, __func__, __LINE__); \
+       }
+
+#define ASSERT(x)   assert(x)
+
+#define DISP_EBI2_LOCAL_DEFINE
+#ifdef DISP_EBI2_LOCAL_DEFINE
+#define LCD_PRIM_BASE_PHYS 0x98000000
+#define LCD_SECD_BASE_PHYS 0x9c000000
+#define EBI2_PRIM_LCD_RS_PIN 0x20000
+#define EBI2_SECD_LCD_RS_PIN 0x20000
+
+#define EBI2_PRIM_LCD_CLR 0xC0
+#define EBI2_PRIM_LCD_SEL 0x40
+
+#define EBI2_SECD_LCD_CLR 0x300
+#define EBI2_SECD_LCD_SEL 0x100
+#endif
+
+extern u32 msm_fb_msg_level;
+
+/*
+ * Message printing priorities:
+ * LEVEL 0 KERN_EMERG (highest priority)
+ * LEVEL 1 KERN_ALERT
+ * LEVEL 2 KERN_CRIT
+ * LEVEL 3 KERN_ERR
+ * LEVEL 4 KERN_WARNING
+ * LEVEL 5 KERN_NOTICE
+ * LEVEL 6 KERN_INFO
+ * LEVEL 7 KERN_DEBUG (Lowest priority)
+ */
+#define MSM_FB_EMERG(msg, ...)    \
+       if (msm_fb_msg_level > 0)  \
+               printk(KERN_EMERG msg, ## __VA_ARGS__);
+#define MSM_FB_ALERT(msg, ...)    \
+       if (msm_fb_msg_level > 1)  \
+               printk(KERN_ALERT msg, ## __VA_ARGS__);
+#define MSM_FB_CRIT(msg, ...)    \
+       if (msm_fb_msg_level > 2)  \
+               printk(KERN_CRIT msg, ## __VA_ARGS__);
+#define MSM_FB_ERR(msg, ...)    \
+       if (msm_fb_msg_level > 3)  \
+               printk(KERN_ERR msg, ## __VA_ARGS__);
+#define MSM_FB_WARNING(msg, ...)    \
+       if (msm_fb_msg_level > 4)  \
+               printk(KERN_WARNING msg, ## __VA_ARGS__);
+#define MSM_FB_NOTICE(msg, ...)    \
+       if (msm_fb_msg_level > 5)  \
+               printk(KERN_NOTICE msg, ## __VA_ARGS__);
+#define MSM_FB_INFO(msg, ...)    \
+       if (msm_fb_msg_level > 6)  \
+               printk(KERN_INFO msg, ## __VA_ARGS__);
+#define MSM_FB_DEBUG(msg, ...)    \
+       if (msm_fb_msg_level > 7)  \
+               printk(KERN_DEBUG msg, ## __VA_ARGS__);
+
+#ifdef MSM_FB_C
+unsigned char *msm_mdp_base;
+unsigned char *msm_pmdh_base;
+unsigned char *msm_emdh_base;
+#else
+extern unsigned char *msm_mdp_base;
+extern unsigned char *msm_pmdh_base;
+extern unsigned char *msm_emdh_base;
+#endif
+
+#endif /* MSM_FB_DEF_H */
diff --git a/drivers/staging/msm/msm_fb_panel.c b/drivers/staging/msm/msm_fb_panel.c
new file mode 100644 (file)
index 0000000..b17a239
--- /dev/null
@@ -0,0 +1,136 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+
+#include "msm_fb_panel.h"
+
+int panel_next_on(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct msm_fb_panel_data *pdata;
+       struct msm_fb_panel_data *next_pdata;
+       struct platform_device *next_pdev;
+
+       pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
+
+       if (pdata) {
+               next_pdev = pdata->next;
+               if (next_pdev) {
+                       next_pdata =
+                           (struct msm_fb_panel_data *)next_pdev->dev.
+                           platform_data;
+                       if ((next_pdata) && (next_pdata->on))
+                               ret = next_pdata->on(next_pdev);
+               }
+       }
+
+       return ret;
+}
+
+int panel_next_off(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct msm_fb_panel_data *pdata;
+       struct msm_fb_panel_data *next_pdata;
+       struct platform_device *next_pdev;
+
+       pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
+
+       if (pdata) {
+               next_pdev = pdata->next;
+               if (next_pdev) {
+                       next_pdata =
+                           (struct msm_fb_panel_data *)next_pdev->dev.
+                           platform_data;
+                       if ((next_pdata) && (next_pdata->on))
+                               ret = next_pdata->off(next_pdev);
+               }
+       }
+
+       return ret;
+}
+
+struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
+                                               u32 type, u32 id)
+{
+       struct platform_device *this_dev = NULL;
+       char dev_name[16];
+
+       switch (type) {
+       case EBI2_PANEL:
+               snprintf(dev_name, sizeof(dev_name), "ebi2_lcd");
+               break;
+
+       case MDDI_PANEL:
+               snprintf(dev_name, sizeof(dev_name), "mddi");
+               break;
+
+       case EXT_MDDI_PANEL:
+               snprintf(dev_name, sizeof(dev_name), "mddi_ext");
+               break;
+
+       case TV_PANEL:
+               snprintf(dev_name, sizeof(dev_name), "tvenc");
+               break;
+
+       case HDMI_PANEL:
+       case LCDC_PANEL:
+               snprintf(dev_name, sizeof(dev_name), "lcdc");
+               break;
+
+       default:
+               return NULL;
+       }
+
+       if (pdata != NULL)
+               pdata->next = NULL;
+       else
+               return NULL;
+
+       this_dev =
+           platform_device_alloc(dev_name, ((u32) type << 16) | (u32) id);
+
+       if (this_dev) {
+               if (platform_device_add_data
+                   (this_dev, pdata, sizeof(struct msm_fb_panel_data))) {
+                       printk
+                           ("msm_fb_device_alloc: platform_device_add_data failed!\n");
+                       platform_device_put(this_dev);
+                       return NULL;
+               }
+       }
+
+       return this_dev;
+}
diff --git a/drivers/staging/msm/msm_fb_panel.h b/drivers/staging/msm/msm_fb_panel.h
new file mode 100644 (file)
index 0000000..ab45831
--- /dev/null
@@ -0,0 +1,145 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MSM_FB_PANEL_H
+#define MSM_FB_PANEL_H
+
+#include "msm_fb_def.h"
+
+struct msm_fb_data_type;
+
+typedef void (*msm_fb_vsync_handler_type) (void *arg);
+
+/* panel id type */
+typedef struct panel_id_s {
+       uint16 id;
+       uint16 type;
+} panel_id_type;
+
+/* panel type list */
+#define NO_PANEL       0xffff  /* No Panel */
+#define MDDI_PANEL     1       /* MDDI */
+#define EBI2_PANEL     2       /* EBI2 */
+#define LCDC_PANEL     3       /* internal LCDC type */
+#define EXT_MDDI_PANEL 4       /* Ext.MDDI */
+#define TV_PANEL       5       /* TV */
+#define HDMI_PANEL     6       /* HDMI TV */
+
+/* panel class */
+typedef enum {
+       DISPLAY_LCD = 0,        /* lcd = ebi2/mddi */
+       DISPLAY_LCDC,           /* lcdc */
+       DISPLAY_TV,             /* TV Out */
+       DISPLAY_EXT_MDDI,       /* External MDDI */
+} DISP_TARGET;
+
+/* panel device locaiton */
+typedef enum {
+       DISPLAY_1 = 0,          /* attached as first device */
+       DISPLAY_2,              /* attached on second device */
+       MAX_PHYS_TARGET_NUM,
+} DISP_TARGET_PHYS;
+
+/* panel info type */
+struct lcd_panel_info {
+       __u32 vsync_enable;
+       __u32 refx100;
+       __u32 v_back_porch;
+       __u32 v_front_porch;
+       __u32 v_pulse_width;
+       __u32 hw_vsync_mode;
+       __u32 vsync_notifier_period;
+};
+
+struct lcdc_panel_info {
+       __u32 h_back_porch;
+       __u32 h_front_porch;
+       __u32 h_pulse_width;
+       __u32 v_back_porch;
+       __u32 v_front_porch;
+       __u32 v_pulse_width;
+       __u32 border_clr;
+       __u32 underflow_clr;
+       __u32 hsync_skew;
+};
+
+struct mddi_panel_info {
+       __u32 vdopkt;
+};
+
+struct msm_panel_info {
+       __u32 xres;
+       __u32 yres;
+       __u32 bpp;
+       __u32 type;
+       __u32 wait_cycle;
+       DISP_TARGET_PHYS pdest;
+       __u32 bl_max;
+       __u32 bl_min;
+       __u32 fb_num;
+       __u32 clk_rate;
+       __u32 clk_min;
+       __u32 clk_max;
+       __u32 frame_count;
+
+       union {
+               struct mddi_panel_info mddi;
+       };
+
+       union {
+               struct lcd_panel_info lcd;
+               struct lcdc_panel_info lcdc;
+       };
+};
+
+struct msm_fb_panel_data {
+       struct msm_panel_info panel_info;
+       void (*set_rect) (int x, int y, int xres, int yres);
+       void (*set_vsync_notifier) (msm_fb_vsync_handler_type, void *arg);
+       void (*set_backlight) (struct msm_fb_data_type *);
+
+       /* function entry chain */
+       int (*on) (struct platform_device *pdev);
+       int (*off) (struct platform_device *pdev);
+       struct platform_device *next;
+};
+
+/*===========================================================================
+  FUNCTIONS PROTOTYPES
+============================================================================*/
+struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
+                                               u32 type, u32 id);
+int panel_next_on(struct platform_device *pdev);
+int panel_next_off(struct platform_device *pdev);
+
+int lcdc_device_register(struct msm_panel_info *pinfo);
+
+int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
+                                       u32 channel, u32 panel);
+
+#endif /* MSM_FB_PANEL_H */
diff --git a/drivers/staging/msm/msm_mdp.h b/drivers/staging/msm/msm_mdp.h
new file mode 100644 (file)
index 0000000..2d5323f
--- /dev/null
@@ -0,0 +1,245 @@
+/* include/linux/msm_mdp.h
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2009-2010, Code Aurora Forum. 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.
+ */
+#ifndef _MSM_MDP_H_
+#define _MSM_MDP_H_
+
+#include <linux/types.h>
+#include <linux/fb.h>
+
+#define MSMFB_IOCTL_MAGIC 'm'
+#define MSMFB_GRP_DISP          _IOW(MSMFB_IOCTL_MAGIC, 1, unsigned int)
+#define MSMFB_BLIT              _IOW(MSMFB_IOCTL_MAGIC, 2, unsigned int)
+#define MSMFB_SUSPEND_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 128, unsigned int)
+#define MSMFB_RESUME_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 129, unsigned int)
+#define MSMFB_CURSOR _IOW(MSMFB_IOCTL_MAGIC, 130, struct fb_cursor)
+#define MSMFB_SET_LUT _IOW(MSMFB_IOCTL_MAGIC, 131, struct fb_cmap)
+#define MSMFB_HISTOGRAM _IOWR(MSMFB_IOCTL_MAGIC, 132, struct mdp_histogram)
+/* new ioctls's for set/get ccs matrix */
+#define MSMFB_GET_CCS_MATRIX  _IOWR(MSMFB_IOCTL_MAGIC, 133, struct mdp_ccs)
+#define MSMFB_SET_CCS_MATRIX  _IOW(MSMFB_IOCTL_MAGIC, 134, struct mdp_ccs)
+#define MSMFB_OVERLAY_SET       _IOWR(MSMFB_IOCTL_MAGIC, 135, \
+                                               struct mdp_overlay)
+#define MSMFB_OVERLAY_UNSET     _IOW(MSMFB_IOCTL_MAGIC, 136, unsigned int)
+#define MSMFB_OVERLAY_PLAY      _IOW(MSMFB_IOCTL_MAGIC, 137, \
+                                               struct msmfb_overlay_data)
+#define MSMFB_GET_PAGE_PROTECTION _IOR(MSMFB_IOCTL_MAGIC, 138, \
+                                       struct mdp_page_protection)
+#define MSMFB_SET_PAGE_PROTECTION _IOW(MSMFB_IOCTL_MAGIC, 139, \
+                                       struct mdp_page_protection)
+#define MSMFB_OVERLAY_GET      _IOR(MSMFB_IOCTL_MAGIC, 140, \
+                                               struct mdp_overlay)
+
+/* new ioctls for async MDP ops */
+#define MSMFB_ASYNC_BLIT _IOW(MSMFB_IOCTL_MAGIC, 141, unsigned int)
+#define MSMFB_BLIT_FLUSH _IOR(MSMFB_IOCTL_MAGIC, 142, unsigned int)
+
+#define MDP_IMGTYPE2_START 0x10000
+
+enum {
+       MDP_RGB_565,      /* RGB 565 planer */
+       MDP_XRGB_8888,    /* RGB 888 padded */
+       MDP_Y_CBCR_H2V2,  /* Y and CbCr, pseudo planer w/ Cb is in MSB */
+       MDP_ARGB_8888,    /* ARGB 888 */
+       MDP_RGB_888,      /* RGB 888 planer */
+       MDP_Y_CRCB_H2V2,  /* Y and CrCb, pseudo planer w/ Cr is in MSB */
+       MDP_YCRYCB_H2V1,  /* YCrYCb interleave */
+       MDP_Y_CRCB_H2V1,  /* Y and CrCb, pseduo planer w/ Cr is in MSB */
+       MDP_Y_CBCR_H2V1,   /* Y and CrCb, pseduo planer w/ Cr is in MSB */
+       MDP_RGBA_8888,    /* ARGB 888 */
+       MDP_BGRA_8888,    /* ABGR 888 */
+       MDP_Y_CRCB_H2V2_TILE,  /* Y and CrCb, pseudo planer tile */
+       MDP_Y_CBCR_H2V2_TILE,  /* Y and CbCr, pseudo planer tile */
+       MDP_IMGTYPE_LIMIT,
+       MDP_BGR_565 = MDP_IMGTYPE2_START,      /* BGR 565 planer */
+       MDP_FB_FORMAT,    /* framebuffer format */
+       MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */
+};
+
+enum {
+       PMEM_IMG,
+       FB_IMG,
+};
+
+/* mdp_blit_req flag values */
+#define MDP_ROT_NOP 0
+#define MDP_FLIP_LR 0x1
+#define MDP_FLIP_UD 0x2
+#define MDP_ROT_90 0x4
+#define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR)
+#define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR)
+#define MDP_DITHER 0x8
+#define MDP_BLUR 0x10
+#define MDP_BLEND_FG_PREMULT 0x20000
+
+#define MDP_DEINTERLACE        0x80000000
+#define MDP_SHARPENING         0x40000000
+
+#define MDP_NO_DMA_BARRIER_START       0x20000000
+#define MDP_NO_DMA_BARRIER_END         0x10000000
+#define MDP_NO_BLIT                    0x08000000
+#define MDP_BLIT_WITH_DMA_BARRIERS     0x000
+#define MDP_BLIT_WITH_NO_DMA_BARRIERS    \
+       (MDP_NO_DMA_BARRIER_START | MDP_NO_DMA_BARRIER_END)
+#define MDP_TRANSP_NOP 0xffffffff
+#define MDP_ALPHA_NOP 0xff
+
+#define MDP_BLIT_SRC_GEM       0x02000000 /* set for GEM, clear for PMEM */
+#define MDP_BLIT_DST_GEM       0x01000000 /* set for GEM, clear for PMEM */
+
+#define MDP_FB_PAGE_PROTECTION_NONCACHED         (0)
+#define MDP_FB_PAGE_PROTECTION_WRITECOMBINE      (1)
+#define MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE (2)
+#define MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE    (3)
+#define MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE  (4)
+/* Sentinel: Don't use! */
+#define MDP_FB_PAGE_PROTECTION_INVALID           (5)
+/* Count of the number of MDP_FB_PAGE_PROTECTION_... values. */
+#define MDP_NUM_FB_PAGE_PROTECTION_VALUES        (5)
+
+struct mdp_rect {
+       uint32_t x;
+       uint32_t y;
+       uint32_t w;
+       uint32_t h;
+};
+
+struct mdp_img {
+       uint32_t width;
+       uint32_t height;
+       uint32_t format;
+       uint32_t offset;
+       int memory_id;          /* the file descriptor */
+       uint32_t priv;
+};
+
+/*
+ * {3x3} + {3} ccs matrix
+ */
+
+#define MDP_CCS_RGB2YUV        0
+#define MDP_CCS_YUV2RGB        1
+
+#define MDP_CCS_SIZE   9
+#define MDP_BV_SIZE    3
+
+struct mdp_ccs {
+       int direction;                  /* MDP_CCS_RGB2YUV or YUV2RGB */
+       uint16_t ccs[MDP_CCS_SIZE];     /* 3x3 color coefficients */
+       uint16_t bv[MDP_BV_SIZE];       /* 1x3 bias vector */
+};
+
+/* The version of the mdp_blit_req structure so that
+ * user applications can selectively decide which functionality
+ * to include
+ */
+
+#define MDP_BLIT_REQ_VERSION 2
+
+struct mdp_blit_req {
+       struct mdp_img src;
+       struct mdp_img dst;
+       struct mdp_rect src_rect;
+       struct mdp_rect dst_rect;
+       uint32_t alpha;
+       uint32_t transp_mask;
+       uint32_t flags;
+       int sharpening_strength;  /* -127 <--> 127, default 64 */
+};
+
+struct mdp_blit_req_list {
+       uint32_t count;
+       struct mdp_blit_req req[];
+};
+
+struct msmfb_data {
+       uint32_t offset;
+       int memory_id;
+       int id;
+};
+
+#define MSMFB_NEW_REQUEST -1
+
+struct msmfb_overlay_data {
+       uint32_t id;
+       struct msmfb_data data;
+};
+
+struct msmfb_img {
+       uint32_t width;
+       uint32_t height;
+       uint32_t format;
+};
+
+struct mdp_overlay {
+       struct msmfb_img src;
+       struct mdp_rect src_rect;
+       struct mdp_rect dst_rect;
+       uint32_t z_order;       /* stage number */
+       uint32_t is_fg;         /* control alpha & transp */
+       uint32_t alpha;
+       uint32_t transp_mask;
+       uint32_t flags;
+       uint32_t id;
+       uint32_t user_data[8];
+};
+
+struct mdp_histogram {
+       uint32_t frame_cnt;
+       uint32_t bin_cnt;
+       uint32_t *r;
+       uint32_t *g;
+       uint32_t *b;
+};
+
+struct mdp_page_protection {
+       uint32_t page_protection;
+};
+
+
+struct msm_panel_common_pdata {
+       int gpio;
+       int (*backlight_level)(int level, int max, int min);
+       int (*pmic_backlight)(int level);
+       int (*panel_num)(void);
+       void (*panel_config_gpio)(int);
+       int *gpio_num;
+};
+
+struct lcdc_platform_data {
+       int (*lcdc_gpio_config)(int on);
+       void (*lcdc_power_save)(int);
+};
+
+struct tvenc_platform_data {
+       int (*pm_vid_en)(int on);
+};
+
+struct mddi_platform_data {
+       void (*mddi_power_save)(int on);
+       int (*mddi_sel_clk)(u32 *clk_rate);
+};
+
+struct msm_fb_platform_data {
+       int (*detect_client)(const char *name);
+       int mddi_prescan;
+       int (*allow_set_offset)(void);
+};
+
+struct msm_hdmi_platform_data {
+       int irq;
+       int (*cable_detect)(int insert);
+};
+
+#endif /*_MSM_MDP_H_*/
diff --git a/drivers/staging/msm/staging-devices.c b/drivers/staging/msm/staging-devices.c
new file mode 100644 (file)
index 0000000..0f8ec3e
--- /dev/null
@@ -0,0 +1,323 @@
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <linux/delay.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+
+#include <mach/board.h>
+#include <mach/irqs.h>
+#include <mach/sirc.h>
+#include <mach/gpio.h>
+
+#include "msm_mdp.h"
+#include "memory_ll.h"
+//#include "android_pmem.h"
+#include <mach/board.h>
+
+#ifdef CONFIG_MSM_SOC_REV_A
+#define MSM_SMI_BASE 0xE0000000
+#else
+#define MSM_SMI_BASE 0x00000000
+#endif
+
+
+#define TOUCHPAD_SUSPEND       34
+#define TOUCHPAD_IRQ           38
+
+#define MSM_PMEM_MDP_SIZE      0x1591000
+
+#ifdef CONFIG_MSM_SOC_REV_A
+#define SMEM_SPINLOCK_I2C      "D:I2C02000021"
+#else
+#define SMEM_SPINLOCK_I2C      "S:6"
+#endif
+
+#define MSM_PMEM_ADSP_SIZE     0x1C00000
+
+#define MSM_FB_SIZE             0x500000
+#define MSM_FB_SIZE_ST15       0x800000
+#define MSM_AUDIO_SIZE         0x80000
+#define MSM_GPU_PHYS_SIZE      SZ_2M
+
+#ifdef CONFIG_MSM_SOC_REV_A
+#define MSM_SMI_BASE           0xE0000000
+#else
+#define MSM_SMI_BASE           0x00000000
+#endif
+
+#define MSM_SHARED_RAM_PHYS    (MSM_SMI_BASE + 0x00100000)
+
+#define MSM_PMEM_SMI_BASE      (MSM_SMI_BASE + 0x02B00000)
+#define MSM_PMEM_SMI_SIZE      0x01500000
+
+#define MSM_FB_BASE            MSM_PMEM_SMI_BASE
+#define MSM_GPU_PHYS_BASE      (MSM_FB_BASE + MSM_FB_SIZE)
+#define MSM_PMEM_SMIPOOL_BASE  (MSM_GPU_PHYS_BASE + MSM_GPU_PHYS_SIZE)
+#define MSM_PMEM_SMIPOOL_SIZE  (MSM_PMEM_SMI_SIZE - MSM_FB_SIZE \
+                                       - MSM_GPU_PHYS_SIZE)
+
+#if defined(CONFIG_FB_MSM_MDP40)
+#define MDP_BASE          0xA3F00000
+#define PMDH_BASE         0xAD600000
+#define EMDH_BASE         0xAD700000
+#define TVENC_BASE        0xAD400000
+#else
+#define MDP_BASE          0xAA200000
+#define PMDH_BASE         0xAA600000
+#define EMDH_BASE         0xAA700000
+#define TVENC_BASE        0xAA400000
+#endif
+
+#define PMEM_KERNEL_EBI1_SIZE  (CONFIG_PMEM_KERNEL_SIZE * 1024 * 1024)
+
+static struct resource msm_fb_resources[] = {
+       {
+               .flags  = IORESOURCE_DMA,
+       }
+};
+
+static struct resource msm_mdp_resources[] = {
+       {
+               .name   = "mdp",
+               .start  = MDP_BASE,
+               .end    = MDP_BASE + 0x000F0000 - 1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device msm_mdp_device = {
+       .name   = "mdp",
+       .id     = 0,
+       .num_resources  = ARRAY_SIZE(msm_mdp_resources),
+       .resource       = msm_mdp_resources,
+};
+
+static struct platform_device msm_lcdc_device = {
+       .name   = "lcdc",
+       .id     = 0,
+};
+
+static int msm_fb_detect_panel(const char *name)
+{
+       int ret = -EPERM;
+
+       if (machine_is_qsd8x50_ffa() || machine_is_qsd8x50a_ffa()) {
+               if (!strncmp(name, "mddi_toshiba_wvga_pt", 20))
+                       ret = 0;
+               else
+                       ret = -ENODEV;
+       } else if ((machine_is_qsd8x50_surf() || machine_is_qsd8x50a_surf())
+                       && !strcmp(name, "lcdc_external"))
+               ret = 0;
+       else if (0 /*machine_is_qsd8x50_grapefruit() */) {
+               if (!strcmp(name, "lcdc_grapefruit_vga"))
+                       ret = 0;
+               else
+                       ret = -ENODEV;
+       } else if (machine_is_qsd8x50_st1()) {
+               if (!strcmp(name, "lcdc_st1_wxga"))
+                       ret = 0;
+               else
+                       ret = -ENODEV;
+       } else if (machine_is_qsd8x50a_st1_5()) {
+               if (!strcmp(name, "lcdc_st15") ||
+                   !strcmp(name, "hdmi_sii9022"))
+                       ret = 0;
+               else
+                       ret = -ENODEV;
+       }
+
+       return ret;
+}
+
+/* Only allow a small subset of machines to set the offset via
+   FB PAN_DISPLAY */
+
+static int msm_fb_allow_set_offset(void)
+{
+       return (machine_is_qsd8x50_st1() ||
+               machine_is_qsd8x50a_st1_5()) ? 1 : 0;
+}
+
+
+static struct msm_fb_platform_data msm_fb_pdata = {
+       .detect_client = msm_fb_detect_panel,
+       .allow_set_offset = msm_fb_allow_set_offset,
+};
+
+static struct platform_device msm_fb_device = {
+       .name   = "msm_fb",
+       .id     = 0,
+       .num_resources  = ARRAY_SIZE(msm_fb_resources),
+       .resource       = msm_fb_resources,
+       .dev    = {
+               .platform_data = &msm_fb_pdata,
+       }
+};
+
+static void __init qsd8x50_allocate_memory_regions(void)
+{
+       void *addr;
+       unsigned long size;
+       if (machine_is_qsd8x50a_st1_5())
+               size = MSM_FB_SIZE_ST15;
+       else
+               size = MSM_FB_SIZE;
+
+       addr = alloc_bootmem(size); // (void *)MSM_FB_BASE;
+       if (!addr)
+               printk("Failed to allocate bootmem for framebuffer\n");
+
+
+       msm_fb_resources[0].start = __pa(addr);
+       msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
+       pr_info(KERN_ERR "using %lu bytes of SMI at %lx physical for fb\n",
+               size, (unsigned long)addr);
+}
+
+static int msm_fb_lcdc_gpio_config(int on)
+{
+//     return 0;
+       if (machine_is_qsd8x50_st1()) {
+               if (on) {
+                       gpio_set_value(32, 1);
+                       mdelay(100);
+                       gpio_set_value(20, 1);
+                       gpio_set_value(17, 1);
+                       gpio_set_value(19, 1);
+               } else {
+                       gpio_set_value(17, 0);
+                       gpio_set_value(19, 0);
+                       gpio_set_value(20, 0);
+                       mdelay(100);
+                       gpio_set_value(32, 0);
+               }
+       } else if (machine_is_qsd8x50a_st1_5()) {
+               if (on) {
+                       gpio_set_value(17, 1);
+                       gpio_set_value(19, 1);
+                       gpio_set_value(20, 1);
+                       gpio_set_value(22, 0);
+                       gpio_set_value(32, 1);
+                       gpio_set_value(155, 1);
+                       //st15_hdmi_power(1);
+                       gpio_set_value(22, 1);
+
+               } else {
+                       gpio_set_value(17, 0);
+                       gpio_set_value(19, 0);
+                       gpio_set_value(22, 0);
+                       gpio_set_value(32, 0);
+                       gpio_set_value(155, 0);
+               //      st15_hdmi_power(0);
+               }
+       }
+       return 0;
+}
+
+
+static struct lcdc_platform_data lcdc_pdata = {
+       .lcdc_gpio_config = msm_fb_lcdc_gpio_config,
+};
+
+static struct msm_gpio msm_fb_st15_gpio_config_data[] = {
+       { GPIO_CFG(17, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en0" },
+       { GPIO_CFG(19, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "dat_pwr_sv" },
+       { GPIO_CFG(20, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lvds_pwr_dn" },
+       { GPIO_CFG(22, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en1" },
+       { GPIO_CFG(32, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en2" },
+       { GPIO_CFG(103, 0, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_irq" },
+       { GPIO_CFG(155, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_3v3" },
+};
+
+static struct msm_panel_common_pdata mdp_pdata = {
+       .gpio = 98,
+};
+
+static struct platform_device *devices[] __initdata = {
+       &msm_fb_device,
+};
+
+
+static void __init msm_register_device(struct platform_device *pdev, void *data)
+{
+       int ret;
+
+       pdev->dev.platform_data = data;
+
+       ret = platform_device_register(pdev);
+       if (ret)
+               dev_err(&pdev->dev,
+                         "%s: platform_device_register() failed = %d\n",
+                         __func__, ret);
+}
+
+void __init msm_fb_register_device(char *name, void *data)
+{
+       if (!strncmp(name, "mdp", 3))
+               msm_register_device(&msm_mdp_device, data);
+/*
+       else if (!strncmp(name, "pmdh", 4))
+               msm_register_device(&msm_mddi_device, data);
+       else if (!strncmp(name, "emdh", 4))
+               msm_register_device(&msm_mddi_ext_device, data);
+       else if (!strncmp(name, "ebi2", 4))
+               msm_register_device(&msm_ebi2_lcd_device, data);
+       else if (!strncmp(name, "tvenc", 5))
+               msm_register_device(&msm_tvenc_device, data);
+       else */
+
+       if (!strncmp(name, "lcdc", 4))
+               msm_register_device(&msm_lcdc_device, data);
+       /*else
+               printk(KERN_ERR "%s: unknown device! %s\n", __func__, name);
+*/
+}
+
+static void __init msm_fb_add_devices(void)
+{
+       int rc;
+       msm_fb_register_device("mdp", &mdp_pdata);
+//     msm_fb_register_device("pmdh", &mddi_pdata);
+//     msm_fb_register_device("emdh", &mddi_pdata);
+//     msm_fb_register_device("tvenc", 0);
+
+       if (machine_is_qsd8x50a_st1_5()) {
+/*             rc = st15_hdmi_vreg_init();
+               if (rc)
+                       return;
+*/
+               rc = msm_gpios_request_enable(
+                       msm_fb_st15_gpio_config_data,
+                       ARRAY_SIZE(msm_fb_st15_gpio_config_data));
+               if (rc) {
+                       printk(KERN_ERR "%s: unable to init lcdc gpios\n",
+                              __func__);
+                       return;
+               }
+               msm_fb_register_device("lcdc", &lcdc_pdata);
+       } else
+               msm_fb_register_device("lcdc", 0);
+}
+
+int __init staging_init_pmem(void)
+{
+       qsd8x50_allocate_memory_regions();
+       return 0;
+}
+
+int __init staging_init_devices(void)
+{
+       platform_add_devices(devices, ARRAY_SIZE(devices));
+       msm_fb_add_devices();
+       return 0;
+}
+
+arch_initcall(staging_init_pmem);
+arch_initcall(staging_init_devices);
diff --git a/drivers/staging/msm/tv_ntsc.c b/drivers/staging/msm/tv_ntsc.c
new file mode 100644 (file)
index 0000000..5eb6761
--- /dev/null
@@ -0,0 +1,163 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+
+#include "msm_fb.h"
+#include "tvenc.h"
+
+#define NTSC_TV_DIMENSION_WIDTH      720
+#define NTSC_TV_DIMENSION_HEIGHT     480
+
+static int ntsc_off(struct platform_device *pdev);
+static int ntsc_on(struct platform_device *pdev);
+
+static int ntsc_on(struct platform_device *pdev)
+{
+       uint32 reg = 0;
+       int ret = 0;
+       struct msm_fb_data_type *mfd;
+
+       mfd = platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       TV_OUT(TV_ENC_CTL, 0);  /* disable TV encoder */
+
+       if (mfd->panel.id == NTSC_M) {
+               /* Cr gain 11, Cb gain C6, y_gain 97 */
+               TV_OUT(TV_GAIN, 0x0081B697);
+       } else {
+               /* Cr gain 11, Cb gain C6, y_gain 97 */
+               TV_OUT(TV_GAIN, 0x008bc4a3);
+               reg |= TVENC_CTL_NTSCJ_MODE;
+       }
+
+       TV_OUT(TV_CGMS, 0x0);
+       /*  NTSC Timing */
+       TV_OUT(TV_SYNC_1, 0x0020009e);
+       TV_OUT(TV_SYNC_2, 0x011306B4);
+       TV_OUT(TV_SYNC_3, 0x0006000C);
+       TV_OUT(TV_SYNC_4, 0x0028020D);
+       TV_OUT(TV_SYNC_5, 0x005E02FB);
+       TV_OUT(TV_SYNC_6, 0x0006000C);
+       TV_OUT(TV_SYNC_7, 0x00000012);
+       TV_OUT(TV_BURST_V1, 0x0013020D);
+       TV_OUT(TV_BURST_V2, 0x0014020C);
+       TV_OUT(TV_BURST_V3, 0x0013020D);
+       TV_OUT(TV_BURST_V4, 0x0014020C);
+       TV_OUT(TV_BURST_H, 0x00AE00F2);
+       TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
+       TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);
+
+       reg |= TVENC_CTL_TV_MODE_NTSC_M_PAL60;
+
+       reg |= TVENC_CTL_Y_FILTER_EN |
+           TVENC_CTL_CR_FILTER_EN |
+           TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN;
+#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO
+       reg |= TVENC_CTL_S_VIDEO_EN;
+#endif
+
+       TV_OUT(TV_LEVEL, 0x00000000);   /* DC offset to 0. */
+       TV_OUT(TV_OFFSET, 0x008080f0);
+
+#ifdef CONFIG_FB_MSM_MDP31
+       TV_OUT(TV_DAC_INTF, 0x29);
+#endif
+       TV_OUT(TV_ENC_CTL, reg);
+
+       reg |= TVENC_CTL_ENC_EN;
+       TV_OUT(TV_ENC_CTL, reg);
+
+       return ret;
+}
+
+static int ntsc_off(struct platform_device *pdev)
+{
+       TV_OUT(TV_ENC_CTL, 0);  /* disable TV encoder */
+       return 0;
+}
+
+static int __init ntsc_probe(struct platform_device *pdev)
+{
+       msm_fb_add_device(pdev);
+
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = ntsc_probe,
+       .driver = {
+               .name   = "tv_ntsc",
+       },
+};
+
+static struct msm_fb_panel_data ntsc_panel_data = {
+       .panel_info.xres = NTSC_TV_DIMENSION_WIDTH,
+       .panel_info.yres = NTSC_TV_DIMENSION_HEIGHT,
+       .panel_info.type = TV_PANEL,
+       .panel_info.pdest = DISPLAY_1,
+       .panel_info.wait_cycle = 0,
+       .panel_info.bpp = 16,
+       .panel_info.fb_num = 2,
+       .on = ntsc_on,
+       .off = ntsc_off,
+};
+
+static struct platform_device this_device = {
+       .name   = "tv_ntsc",
+       .id     = 0,
+       .dev    = {
+               .platform_data = &ntsc_panel_data,
+       }
+};
+
+static int __init ntsc_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&this_driver);
+       if (!ret) {
+               ret = platform_device_register(&this_device);
+               if (ret)
+                       platform_driver_unregister(&this_driver);
+       }
+
+       return ret;
+}
+
+module_init(ntsc_init);
\ No newline at end of file
diff --git a/drivers/staging/msm/tv_pal.c b/drivers/staging/msm/tv_pal.c
new file mode 100644 (file)
index 0000000..204da51
--- /dev/null
@@ -0,0 +1,213 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+
+#include "msm_fb.h"
+#include "tvenc.h"
+
+#ifdef CONFIG_FB_MSM_TVOUT_PAL_M
+#define PAL_TV_DIMENSION_WIDTH      720
+#define PAL_TV_DIMENSION_HEIGHT     480
+#else
+#define PAL_TV_DIMENSION_WIDTH      720
+#define PAL_TV_DIMENSION_HEIGHT     576
+#endif
+
+static int pal_on(struct platform_device *pdev)
+{
+       uint32 reg = 0;
+       int ret = 0;
+       struct msm_fb_data_type *mfd;
+
+       mfd = platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       TV_OUT(TV_ENC_CTL, 0);  /* disable TV encoder */
+
+       switch (mfd->panel.id) {
+       case PAL_BDGHIN:
+               /* Cr gain 11, Cb gain C6, y_gain 97 */
+               TV_OUT(TV_GAIN, 0x0088c1a0);
+               TV_OUT(TV_CGMS, 0x00012345);
+               TV_OUT(TV_TEST_MUX, 0x0);
+               /*  PAL Timing */
+               TV_OUT(TV_SYNC_1, 0x00180097);
+               TV_OUT(TV_SYNC_2, 0x011f06c0);
+               TV_OUT(TV_SYNC_3, 0x0005000a);
+               TV_OUT(TV_SYNC_4, 0x00320271);
+               TV_OUT(TV_SYNC_5, 0x005602f9);
+               TV_OUT(TV_SYNC_6, 0x0005000a);
+               TV_OUT(TV_SYNC_7, 0x0000000f);
+               TV_OUT(TV_BURST_V1, 0x0012026e);
+               TV_OUT(TV_BURST_V2, 0x0011026d);
+               TV_OUT(TV_BURST_V3, 0x00100270);
+               TV_OUT(TV_BURST_V4, 0x0013026f);
+               TV_OUT(TV_BURST_H, 0x00af00ea);
+               TV_OUT(TV_SOL_REQ_ODD, 0x0030026e);
+               TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f);
+
+               reg |= TVENC_CTL_TV_MODE_PAL_BDGHIN;
+               break;
+       case PAL_M:
+               /* Cr gain 11, Cb gain C6, y_gain 97 */
+               TV_OUT(TV_GAIN, 0x0081b697);
+               TV_OUT(TV_CGMS, 0x000af317);
+               TV_OUT(TV_TEST_MUX, 0x000001c3);
+               TV_OUT(TV_TEST_MODE, 0x00000002);
+               /*  PAL Timing */
+               TV_OUT(TV_SYNC_1, 0x0020009e);
+               TV_OUT(TV_SYNC_2, 0x011306b4);
+               TV_OUT(TV_SYNC_3, 0x0006000c);
+               TV_OUT(TV_SYNC_4, 0x0028020D);
+               TV_OUT(TV_SYNC_5, 0x005e02fb);
+               TV_OUT(TV_SYNC_6, 0x0006000c);
+               TV_OUT(TV_SYNC_7, 0x00000012);
+               TV_OUT(TV_BURST_V1, 0x0012020b);
+               TV_OUT(TV_BURST_V2, 0x0016020c);
+               TV_OUT(TV_BURST_V3, 0x00150209);
+               TV_OUT(TV_BURST_V4, 0x0013020c);
+               TV_OUT(TV_BURST_H, 0x00bf010b);
+               TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
+               TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);
+
+               reg |= TVENC_CTL_TV_MODE_PAL_M;
+               break;
+       case PAL_N:
+               /* Cr gain 11, Cb gain C6, y_gain 97 */
+               TV_OUT(TV_GAIN, 0x0081b697);
+               TV_OUT(TV_CGMS, 0x000af317);
+               TV_OUT(TV_TEST_MUX, 0x000001c3);
+               TV_OUT(TV_TEST_MODE, 0x00000002);
+               /*  PAL Timing */
+               TV_OUT(TV_SYNC_1, 0x00180097);
+               TV_OUT(TV_SYNC_2, 0x12006c0);
+               TV_OUT(TV_SYNC_3, 0x0005000a);
+               TV_OUT(TV_SYNC_4, 0x00320271);
+               TV_OUT(TV_SYNC_5, 0x005602f9);
+               TV_OUT(TV_SYNC_6, 0x0005000a);
+               TV_OUT(TV_SYNC_7, 0x0000000f);
+               TV_OUT(TV_BURST_V1, 0x0012026e);
+               TV_OUT(TV_BURST_V2, 0x0011026d);
+               TV_OUT(TV_BURST_V3, 0x00100270);
+               TV_OUT(TV_BURST_V4, 0x0013026f);
+               TV_OUT(TV_BURST_H, 0x00af00fa);
+               TV_OUT(TV_SOL_REQ_ODD, 0x0030026e);
+               TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f);
+
+               reg |= TVENC_CTL_TV_MODE_PAL_N;
+               break;
+
+       default:
+               return -ENODEV;
+       }
+
+       reg |= TVENC_CTL_Y_FILTER_EN |
+           TVENC_CTL_CR_FILTER_EN |
+           TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN;
+#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO
+       reg |= TVENC_CTL_S_VIDEO_EN;
+#endif
+
+       TV_OUT(TV_LEVEL, 0x00000000);   /* DC offset to 0. */
+       TV_OUT(TV_OFFSET, 0x008080f0);
+
+#ifdef CONFIG_FB_MSM_MDP31
+       TV_OUT(TV_DAC_INTF, 0x29);
+#endif
+       TV_OUT(TV_ENC_CTL, reg);
+
+       reg |= TVENC_CTL_ENC_EN;
+       TV_OUT(TV_ENC_CTL, reg);
+
+       return ret;
+}
+
+static int pal_off(struct platform_device *pdev)
+{
+       TV_OUT(TV_ENC_CTL, 0);  /* disable TV encoder */
+       return 0;
+}
+
+static int __init pal_probe(struct platform_device *pdev)
+{
+       msm_fb_add_device(pdev);
+
+       return 0;
+}
+
+static struct platform_driver this_driver = {
+       .probe  = pal_probe,
+       .driver = {
+               .name   = "tv_pal",
+       },
+};
+
+static struct msm_fb_panel_data pal_panel_data = {
+       .panel_info.xres = PAL_TV_DIMENSION_WIDTH,
+       .panel_info.yres = PAL_TV_DIMENSION_HEIGHT,
+       .panel_info.type = TV_PANEL,
+       .panel_info.pdest = DISPLAY_1,
+       .panel_info.wait_cycle = 0,
+       .panel_info.bpp = 16,
+       .panel_info.fb_num = 2,
+       .on = pal_on,
+       .off = pal_off,
+};
+
+static struct platform_device this_device = {
+       .name   = "tv_pal",
+       .id     = 0,
+       .dev    = {
+               .platform_data = &pal_panel_data,
+       }
+};
+
+static int __init pal_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&this_driver);
+       if (!ret) {
+               ret = platform_device_register(&this_device);
+               if (ret)
+                       platform_driver_unregister(&this_driver);
+       }
+
+       return ret;
+}
+
+module_init(pal_init);
diff --git a/drivers/staging/msm/tvenc.c b/drivers/staging/msm/tvenc.c
new file mode 100644 (file)
index 0000000..f41c5ac
--- /dev/null
@@ -0,0 +1,295 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos_params.h>
+
+#define TVENC_C
+#include "tvenc.h"
+#include "msm_fb.h"
+
+static int tvenc_probe(struct platform_device *pdev);
+static int tvenc_remove(struct platform_device *pdev);
+
+static int tvenc_off(struct platform_device *pdev);
+static int tvenc_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static struct clk *tvenc_clk;
+static struct clk *tvdac_clk;
+
+static struct platform_driver tvenc_driver = {
+       .probe = tvenc_probe,
+       .remove = tvenc_remove,
+       .suspend = NULL,
+//     .suspend_late = NULL,
+//     .resume_early = NULL,
+       .resume = NULL,
+       .shutdown = NULL,
+       .driver = {
+                  .name = "tvenc",
+                  },
+};
+
+static struct tvenc_platform_data *tvenc_pdata;
+
+static int tvenc_off(struct platform_device *pdev)
+{
+       int ret = 0;
+
+       ret = panel_next_off(pdev);
+
+       clk_disable(tvenc_clk);
+       clk_disable(tvdac_clk);
+
+       if (tvenc_pdata && tvenc_pdata->pm_vid_en)
+               ret = tvenc_pdata->pm_vid_en(0);
+
+       //pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
+       //                              PM_QOS_DEFAULT_VALUE);
+
+       if (ret)
+               printk(KERN_ERR "%s: pm_vid_en(off) failed! %d\n",
+               __func__, ret);
+
+       return ret;
+}
+
+static int tvenc_on(struct platform_device *pdev)
+{
+       int ret = 0;
+
+//     pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
+//                             128000);
+       if (tvenc_pdata && tvenc_pdata->pm_vid_en)
+               ret = tvenc_pdata->pm_vid_en(1);
+
+       if (ret) {
+               printk(KERN_ERR "%s: pm_vid_en(on) failed! %d\n",
+               __func__, ret);
+               return ret;
+       }
+
+       clk_enable(tvenc_clk);
+       clk_enable(tvdac_clk);
+
+       ret = panel_next_on(pdev);
+
+       return ret;
+}
+
+void tvenc_gen_test_pattern(struct msm_fb_data_type *mfd)
+{
+       uint32 reg = 0, i;
+
+       reg = readl(MSM_TV_ENC_CTL);
+       reg |= TVENC_CTL_TEST_PATT_EN;
+
+       for (i = 0; i < 3; i++) {
+               TV_OUT(TV_ENC_CTL, 0);  /* disable TV encoder */
+
+               switch (i) {
+                       /*
+                        * TV Encoder - Color Bar Test Pattern
+                        */
+               case 0:
+                       reg |= TVENC_CTL_TPG_CLRBAR;
+                       break;
+                       /*
+                        * TV Encoder - Red Frame Test Pattern
+                        */
+               case 1:
+                       reg |= TVENC_CTL_TPG_REDCLR;
+                       break;
+                       /*
+                        * TV Encoder - Modulated Ramp Test Pattern
+                        */
+               default:
+                       reg |= TVENC_CTL_TPG_MODRAMP;
+                       break;
+               }
+
+               TV_OUT(TV_ENC_CTL, reg);
+               mdelay(5000);
+
+               switch (i) {
+                       /*
+                        * TV Encoder - Color Bar Test Pattern
+                        */
+               case 0:
+                       reg &= ~TVENC_CTL_TPG_CLRBAR;
+                       break;
+                       /*
+                        * TV Encoder - Red Frame Test Pattern
+                        */
+               case 1:
+                       reg &= ~TVENC_CTL_TPG_REDCLR;
+                       break;
+                       /*
+                        * TV Encoder - Modulated Ramp Test Pattern
+                        */
+               default:
+                       reg &= ~TVENC_CTL_TPG_MODRAMP;
+                       break;
+               }
+       }
+}
+
+static int tvenc_resource_initialized;
+
+static int tvenc_probe(struct platform_device *pdev)
+{
+       struct msm_fb_data_type *mfd;
+       struct platform_device *mdp_dev = NULL;
+       struct msm_fb_panel_data *pdata = NULL;
+       int rc;
+
+       if (pdev->id == 0) {
+               tvenc_base = ioremap(pdev->resource[0].start,
+                                       pdev->resource[0].end -
+                                       pdev->resource[0].start + 1);
+               if (!tvenc_base) {
+                       printk(KERN_ERR
+                               "tvenc_base ioremap failed!\n");
+                       return -ENOMEM;
+               }
+               tvenc_pdata = pdev->dev.platform_data;
+               tvenc_resource_initialized = 1;
+               return 0;
+       }
+
+       if (!tvenc_resource_initialized)
+               return -EPERM;
+
+       mfd = platform_get_drvdata(pdev);
+
+       if (!mfd)
+               return -ENODEV;
+
+       if (mfd->key != MFD_KEY)
+               return -EINVAL;
+
+       if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+               return -ENOMEM;
+
+       if (tvenc_base == NULL)
+               return -ENOMEM;
+
+       mdp_dev = platform_device_alloc("mdp", pdev->id);
+       if (!mdp_dev)
+               return -ENOMEM;
+
+       /*
+        * link to the latest pdev
+        */
+       mfd->pdev = mdp_dev;
+       mfd->dest = DISPLAY_TV;
+
+       /*
+        * alloc panel device data
+        */
+       if (platform_device_add_data
+           (mdp_dev, pdev->dev.platform_data,
+            sizeof(struct msm_fb_panel_data))) {
+               printk(KERN_ERR "tvenc_probe: platform_device_add_data failed!\n");
+               platform_device_put(mdp_dev);
+               return -ENOMEM;
+       }
+       /*
+        * data chain
+        */
+       pdata = mdp_dev->dev.platform_data;
+       pdata->on = tvenc_on;
+       pdata->off = tvenc_off;
+       pdata->next = pdev;
+
+       /*
+        * get/set panel specific fb info
+        */
+       mfd->panel_info = pdata->panel_info;
+       mfd->fb_imgType = MDP_YCRYCB_H2V1;
+
+       /*
+        * set driver data
+        */
+       platform_set_drvdata(mdp_dev, mfd);
+
+       /*
+        * register in mdp driver
+        */
+       rc = platform_device_add(mdp_dev);
+       if (rc)
+               goto tvenc_probe_err;
+
+       pdev_list[pdev_list_cnt++] = pdev;
+       return 0;
+
+tvenc_probe_err:
+       platform_device_put(mdp_dev);
+       return rc;
+}
+
+static int tvenc_remove(struct platform_device *pdev)
+{
+//     pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc");
+       return 0;
+}
+
+static int tvenc_register_driver(void)
+{
+       return platform_driver_register(&tvenc_driver);
+}
+
+static int __init tvenc_driver_init(void)
+{
+       tvenc_clk = clk_get(NULL, "tv_enc_clk");
+       tvdac_clk = clk_get(NULL, "tv_dac_clk");
+
+       if (IS_ERR(tvenc_clk)) {
+               printk(KERN_ERR "error: can't get tvenc_clk!\n");
+               return IS_ERR(tvenc_clk);
+       }
+
+       if (IS_ERR(tvdac_clk)) {
+               printk(KERN_ERR "error: can't get tvdac_clk!\n");
+               return IS_ERR(tvdac_clk);
+       }
+
+//     pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
+//                             PM_QOS_DEFAULT_VALUE);
+       return tvenc_register_driver();
+}
+
+module_init(tvenc_driver_init);
diff --git a/drivers/staging/msm/tvenc.h b/drivers/staging/msm/tvenc.h
new file mode 100644 (file)
index 0000000..a682dbe
--- /dev/null
@@ -0,0 +1,117 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef TVENC_H
+#define TVENC_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include "msm_fb_panel.h"
+
+#define NTSC_M         0 /* North America, Korea */
+#define NTSC_J         1 /* Japan */
+#define PAL_BDGHIN     2 /* Non-argentina PAL-N */
+#define PAL_M          3 /* PAL-M */
+#define PAL_N          4 /* Argentina PAL-N */
+
+/* 3.57954545 Mhz */
+#define TVENC_CTL_TV_MODE_NTSC_M_PAL60  0
+/* 3.57961149 Mhz */
+#define TVENC_CTL_TV_MODE_PAL_M             BIT(0)
+/*non-Argintina = 4.3361875 Mhz */
+#define TVENC_CTL_TV_MODE_PAL_BDGHIN        BIT(1)
+/*Argentina = 3.582055625 Mhz */
+#define TVENC_CTL_TV_MODE_PAL_N             (BIT(1)|BIT(0))
+
+#define TVENC_CTL_ENC_EN                    BIT(2)
+#define TVENC_CTL_CC_EN                     BIT(3)
+#define TVENC_CTL_CGMS_EN                   BIT(4)
+#define TVENC_CTL_MACRO_EN                  BIT(5)
+#define TVENC_CTL_Y_FILTER_W_NOTCH          BIT(6)
+#define TVENC_CTL_Y_FILTER_WO_NOTCH         0
+#define TVENC_CTL_Y_FILTER_EN               BIT(7)
+#define TVENC_CTL_CR_FILTER_EN              BIT(8)
+#define TVENC_CTL_CB_FILTER_EN              BIT(9)
+#define TVENC_CTL_SINX_FILTER_EN            BIT(10)
+#define TVENC_CTL_TEST_PATT_EN              BIT(11)
+#define TVENC_CTL_OUTPUT_INV                BIT(12)
+#define TVENC_CTL_PAL60_MODE                BIT(13)
+#define TVENC_CTL_NTSCJ_MODE                BIT(14)
+#define TVENC_CTL_TPG_CLRBAR                0
+#define TVENC_CTL_TPG_MODRAMP               BIT(15)
+#define TVENC_CTL_TPG_REDCLR                BIT(16)
+#define TVENC_CTL_S_VIDEO_EN                BIT(19)
+
+#ifdef TVENC_C
+void *tvenc_base;
+#else
+extern void *tvenc_base;
+#endif
+
+#define TV_OUT(reg, v)  writel(v, tvenc_base + MSM_##reg)
+
+#define MSM_TV_ENC_CTL                 0x00
+#define MSM_TV_LEVEL                   0x04
+#define MSM_TV_GAIN                    0x08
+#define MSM_TV_OFFSET                  0x0c
+#define MSM_TV_CGMS                    0x10
+#define MSM_TV_SYNC_1                  0x14
+#define MSM_TV_SYNC_2                  0x18
+#define MSM_TV_SYNC_3                  0x1c
+#define MSM_TV_SYNC_4                  0x20
+#define MSM_TV_SYNC_5                  0x24
+#define MSM_TV_SYNC_6                  0x28
+#define MSM_TV_SYNC_7                  0x2c
+#define MSM_TV_BURST_V1                        0x30
+#define MSM_TV_BURST_V2                        0x34
+#define MSM_TV_BURST_V3                        0x38
+#define MSM_TV_BURST_V4                        0x3c
+#define MSM_TV_BURST_H                 0x40
+#define MSM_TV_SOL_REQ_ODD             0x44
+#define MSM_TV_SOL_REQ_EVEN            0x48
+#define MSM_TV_DAC_CTL                 0x4c
+#define MSM_TV_TEST_MUX                        0x50
+#define MSM_TV_TEST_MODE               0x54
+#define MSM_TV_TEST_MISR_RESET         0x58
+#define MSM_TV_TEST_EXPORT_MISR                0x5c
+#define MSM_TV_TEST_MISR_CURR_VAL      0x60
+#define MSM_TV_TEST_SOF_CFG            0x64
+#define MSM_TV_DAC_INTF                        0x100
+
+#endif /* TVENC_H */
index d3c65d315a2e4cec4e297d0988b7b2542ab3486c..1b56119a765752c76440f4f5a76d5a527c526ed1 100644 (file)
@@ -1,5 +1,5 @@
 config IDE_PHISON
        tristate "PCIE ATA PS5000 IDE support"
-       depends on PCI && ATA && ATA_SFF
+       depends on PCI && ATA && ATA_SFF && ATA_BMDMA
        ---help---
          This is an experimental driver for PS5000 IDE driver.
index 112da7a6c417a9886b337f301f25af465797c346..6b8268d3dc75a776b190694128fcbb4f43bf342e 100644 (file)
@@ -2522,6 +2522,8 @@ int rt28xx_sta_ioctl(IN struct net_device *net_dev,
                        Status =
                            copy_to_user(erq->pointer, pAd->nickname,
                                         erq->length);
+                       if (Status)
+                               Status = -EFAULT;
                        break;
                }
        case SIOCGIWRATE:       /*get default bit rate (bps) */
index b740662d095a5281a2ffd8933fe1473952fd64ae..674769d2b59b0e7c35b8fc9b58d02cca48a23fe2 100644 (file)
@@ -77,6 +77,7 @@ struct usb_device_id rtusb_usb_id[] = {
        {USB_DEVICE(0x083A, 0x7522)},   /* Arcadyan */
        {USB_DEVICE(0x0CDE, 0x0022)},   /* ZCOM */
        {USB_DEVICE(0x0586, 0x3416)},   /* Zyxel */
+       {USB_DEVICE(0x0586, 0x341a)},   /* Zyxel NWD-270N */
        {USB_DEVICE(0x0CDE, 0x0025)},   /* Zyxel */
        {USB_DEVICE(0x1740, 0x9701)},   /* EnGenius */
        {USB_DEVICE(0x1740, 0x9702)},   /* EnGenius */
index dacefea78113414e16fdbe966c41e4334e47d9f4..49ab9fa9ffa784833e08b170d009046c7dd7370a 100644 (file)
@@ -66,8 +66,6 @@ static int hwseqnum = 0;
 static int hwwep = 0;
 static int channels = 0x3fff;
 
-#define eqMacAddr(a, b)                (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1 : 0)
-#define cpMacAddr(des, src)            ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5])
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl);
 MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
index 447d6474a70c3ee3962920e38766307734188c3d..1b6890611fb6dc822156e6ffbee719fb156712c3 100644 (file)
@@ -112,28 +112,29 @@ u32 rt_global_debug_component = \
 #define CAM_CONTENT_COUNT 8
 
 static const struct usb_device_id rtl8192_usb_id_tbl[] = {
-       /* Realtek */
-       {USB_DEVICE(0x0bda, 0x8171)},
-       {USB_DEVICE(0x0bda, 0x8192)},
-       {USB_DEVICE(0x0bda, 0x8709)},
-       /* Corega */
-       {USB_DEVICE(0x07aa, 0x0043)},
-       /* Belkin */
-       {USB_DEVICE(0x050d, 0x805E)},
-       {USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */
-       /* Sitecom */
-       {USB_DEVICE(0x0df6, 0x0031)},
-       {USB_DEVICE(0x0df6, 0x004b)},   /* WL-349 */
-       /* EnGenius */
-       {USB_DEVICE(0x1740, 0x9201)},
-       /* Dlink */
-       {USB_DEVICE(0x2001, 0x3301)},
-       /* Zinwell */
-       {USB_DEVICE(0x5a57, 0x0290)},
-       /* Guillemot */
-       {USB_DEVICE(0x06f8, 0xe031)},
-       //92SU
+       {USB_DEVICE(0x0bda, 0x8171)}, /* Realtek */
        {USB_DEVICE(0x0bda, 0x8172)},
+       {USB_DEVICE(0x0bda, 0x8173)},
+       {USB_DEVICE(0x0bda, 0x8174)},
+       {USB_DEVICE(0x0bda, 0x8712)},
+       {USB_DEVICE(0x0bda, 0x8713)},
+       {USB_DEVICE(0x07aa, 0x0047)},
+       {USB_DEVICE(0x07d1, 0x3303)},
+       {USB_DEVICE(0x07d1, 0x3302)},
+       {USB_DEVICE(0x07d1, 0x3300)},
+       {USB_DEVICE(0x1740, 0x9603)},
+       {USB_DEVICE(0x1740, 0x9605)},
+       {USB_DEVICE(0x050d, 0x815F)},
+       {USB_DEVICE(0x06f8, 0xe031)},
+       {USB_DEVICE(0x7392, 0x7611)},
+       {USB_DEVICE(0x7392, 0x7612)},
+       {USB_DEVICE(0x7392, 0x7622)},
+       {USB_DEVICE(0x0DF6, 0x0045)},
+       {USB_DEVICE(0x0E66, 0x0015)},
+       {USB_DEVICE(0x0E66, 0x0016)},
+       {USB_DEVICE(0x0b05, 0x1786)},
+       /* these are not in the official list */
+       {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */
        {}
 };
 
index 2bede271a2f0302924ea8f2155b5848429073041..f38472c2e75cc78847c191883b28e781d712805a 100644 (file)
@@ -121,6 +121,8 @@ static const struct usb_device_id rtl8192_usb_id_tbl[] = {
        {USB_DEVICE(0x2001, 0x3301)},
        /* Zinwell */
        {USB_DEVICE(0x5a57, 0x0290)},
+       /* LG */
+       {USB_DEVICE(0x043e, 0x7a01)},
        {}
 };
 
index 0332c370fd8285c884fbd602369468788d13903f..ecbde3467b1b90bbcc5a105eb2d2fa8117904391 100644 (file)
@@ -594,8 +594,10 @@ static int sep_allocate_data_pool_memory_handler(struct sep_device *sep,
        dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
 
        error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t));
-       if (error)
+       if (error) {
+               error = -EFAULT;
                goto end_function;
+       }
 
        /* allocate memory */
        if ((sep->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
@@ -609,8 +611,10 @@ static int sep_allocate_data_pool_memory_handler(struct sep_device *sep,
 
        /* write the memory back to the user space */
        error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t));
-       if (error)
+       if (error) {
+               error = -EFAULT;
                goto end_function;
+       }
 
        /* set the allocation */
        sep->data_pool_bytes_allocated += command_args.num_bytes;
@@ -661,6 +665,8 @@ static int sep_write_into_data_pool_handler(struct sep_device *sep, unsigned lon
        }
        /* copy the application data */
        error = copy_from_user(virt_address, (void *) app_in_address, num_bytes);
+       if (error)
+               error = -EFAULT;
 end_function:
        dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
        return error;
@@ -711,6 +717,8 @@ static int sep_read_from_data_pool_handler(struct sep_device *sep, unsigned long
 
        /* copy the application data */
        error = copy_to_user((void *) app_out_address, virt_address, num_bytes);
+       if (error)
+               error = -EFAULT;
 end_function:
        dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
        return error;
@@ -1448,8 +1456,10 @@ static int sep_create_sync_dma_tables_handler(struct sep_device *sep,
        dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
 
        error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t));
-       if (error)
+       if (error) {
+               error = -EFAULT;
                goto end_function;
+       }
 
        edbg("app_in_address is %08lx\n", command_args.app_in_address);
        edbg("app_out_address is %08lx\n", command_args.app_out_address);
@@ -1799,8 +1809,10 @@ static int sep_create_flow_dma_tables_handler(struct sep_device *sep,
                goto end_function;
 
        error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_flow_table_t));
-       if (error)
+       if (error) {
+               error = -EFAULT;
                goto end_function;
+       }
 
        /* create flow tables */
        error = sep_prepare_flow_dma_tables(sep, command_args.num_virtual_buffers, command_args.virt_buff_data_addr, flow_context_ptr, &first_table_data, &last_table_data, command_args.isKernelVirtualAddress);
@@ -1819,8 +1831,10 @@ static int sep_create_flow_dma_tables_handler(struct sep_device *sep,
 
        /* send the parameters to user application */
        error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_build_flow_table_t));
-       if (error)
+       if (error) {
+               error = -EFAULT;
                goto end_function_with_error;
+       }
 
        /* all the flow created  - update the flow entry with temp id */
        flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
@@ -1861,8 +1875,10 @@ static int sep_add_flow_tables_handler(struct sep_device *sep, unsigned long arg
 
        /* get input parameters */
        error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_flow_table_t));
-       if (error)
+       if (error) {
+               error = -EFAULT;
                goto end_function;
+       }
 
        /* find the flow structure for the flow id */
        flow_context_ptr = sep_find_flow_context(sep, command_args.flow_id);
@@ -1933,6 +1949,8 @@ static int sep_add_flow_tables_handler(struct sep_device *sep, unsigned long arg
 
        /* send the parameters to user application */
        error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_add_flow_table_t));
+       if (error)
+               error = -EFAULT;
 end_function_with_error:
        /* free the allocated tables */
        sep_deallocated_flow_tables(&first_table_data);
@@ -1953,8 +1971,10 @@ static int sep_add_flow_tables_message_handler(struct sep_device *sep, unsigned
        dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
 
        error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t));
-       if (error)
+       if (error) {
+               error = -EFAULT;
                goto end_function;
+       }
 
        /* check input */
        if (command_args.message_size_in_bytes > SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
@@ -1970,6 +1990,8 @@ static int sep_add_flow_tables_message_handler(struct sep_device *sep, unsigned
        /* copy the message into context */
        flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
        error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes);
+       if (error)
+               error = -EFAULT;
 end_function:
        dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
        return error;
@@ -1994,6 +2016,8 @@ static int sep_get_static_pool_addr_handler(struct sep_device *sep, unsigned lon
 
        /* send the parameters to user application */
        error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t));
+       if (error)
+               error = -EFAULT;
        dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
        return error;
 }
@@ -2010,8 +2034,10 @@ static int sep_get_physical_mapped_offset_handler(struct sep_device *sep, unsign
        dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
 
        error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t));
-       if (error)
+       if (error) {
+               error = -EFAULT;
                goto end_function;
+       }
 
        if (command_args.physical_address < sep->shared_bus) {
                error = -EINVAL;
@@ -2025,6 +2051,8 @@ static int sep_get_physical_mapped_offset_handler(struct sep_device *sep, unsign
 
        /* send the parameters to user application */
        error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t));
+       if (error)
+               error = -EFAULT;
 end_function:
        dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
        return error;
@@ -2070,11 +2098,11 @@ static int sep_init_handler(struct sep_device *sep, unsigned long arg)
        error = 0;
 
        error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t));
-
-       dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
-
-       if (error)
+       if (error) {
+               error = -EFAULT;
                goto end_function;
+       }
+       dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user\n");
 
        /* PATCH - configure the DMA to single -burst instead of multi-burst */
        /*sep_configure_dma_burst(); */
index 5fe759cc2ee9bab49d53648efea14245d288ed7a..3657e33e88178694daf970d930f77a17e0b193ad 100644 (file)
@@ -2,7 +2,8 @@ config VIDEO_TM6000
        tristate "TV Master TM5600/6000/6010 driver"
        depends on VIDEO_DEV && I2C && INPUT && USB && EXPERIMENTAL
        select VIDEO_TUNER
-       select TUNER_XC2028
+       select MEDIA_TUNER_XC2028
+       select MEDIA_TUNER_XC5000
        select VIDEOBUF_VMALLOC
        help
          Support for TM5600/TM6000/TM6010 USB Device
index bc89f9d280027239986b0d33ec46f50d36443241..273e26ede650415f44f019c250cf8f003daab63c 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/usb.h>
+#include <linux/slab.h>
 
 #include <asm/delay.h>
 #include <sound/core.h>
@@ -410,5 +411,28 @@ error:
        snd_card_free(card);
        return rc;
 }
-EXPORT_SYMBOL_GPL(tm6000_audio_init);
 
+static int tm6000_audio_fini(struct tm6000_core *dev)
+{
+       return 0;
+}
+
+struct tm6000_ops audio_ops = {
+       .id     = TM6000_AUDIO,
+       .name   = "TM6000 Audio Extension",
+       .init   = tm6000_audio_init,
+       .fini   = tm6000_audio_fini,
+};
+
+static int __init tm6000_alsa_register(void)
+{
+       return tm6000_register_extension(&audio_ops);
+}
+
+static void __exit tm6000_alsa_unregister(void)
+{
+       tm6000_unregister_extension(&audio_ops);
+}
+
+module_init(tm6000_alsa_register);
+module_exit(tm6000_alsa_unregister);
index 6143e20d139da525178dcab356109582d5a8ebf8..6a9ae40c7c6dac2a2b60c5afa06e05ab2f928986 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/i2c.h>
 #include <linux/usb.h>
 #include <linux/version.h>
+#include <linux/slab.h>
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
 #include <media/tvaudio.h>
@@ -363,13 +364,7 @@ int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
                tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
                                        0x02, arg);
                msleep(10);
-               rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                       TM6000_GPIO_CLK, 0);
-               if (rc < 0)
-                       return rc;
-               msleep(10);
-               rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                       TM6000_GPIO_CLK, 1);
+               rc = tm6000_i2c_reset(dev, 10);
                break;
        case XC2028_TUNER_RESET:
                /* Reset codes during load firmware */
@@ -423,14 +418,7 @@ int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
                        break;
 
                case 2:
-                       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                               TM6000_GPIO_CLK, 0);
-                       if (rc < 0)
-                               return rc;
-                       msleep(100);
-                       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                               TM6000_GPIO_CLK, 1);
-                       msleep(100);
+                       rc = tm6000_i2c_reset(dev, 100);
                        break;
                }
        }
@@ -563,7 +551,7 @@ static void tm6000_config_tuner(struct tm6000_core *dev)
 
        switch (dev->tuner_type) {
        case TUNER_XC2028:
-               tun_setup.tuner_callback = tm6000_tuner_callback;;
+               tun_setup.tuner_callback = tm6000_tuner_callback;
                break;
        case TUNER_XC5000:
                tun_setup.tuner_callback = tm6000_xc5000_callback;
@@ -692,6 +680,10 @@ static int tm6000_init_dev(struct tm6000_core *dev)
        if (rc < 0)
                goto err;
 
+       tm6000_add_into_devlist(dev);
+
+       tm6000_init_extension(dev);
+
        if (dev->caps.has_dvb) {
                dev->dvb = kzalloc(sizeof(*(dev->dvb)), GFP_KERNEL);
                if (!dev->dvb) {
@@ -921,6 +913,25 @@ static void tm6000_usb_disconnect(struct usb_interface *interface)
        }
 #endif
 
+       if (dev->gpio.power_led) {
+               switch (dev->model) {
+               case TM6010_BOARD_HAUPPAUGE_900H:
+               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+               case TM6010_BOARD_TWINHAN_TU501:
+                       /* Power led off */
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x01);
+                       msleep(15);
+                       break;
+               case TM6010_BOARD_BEHOLD_WANDER:
+               case TM6010_BOARD_BEHOLD_VOYAGER:
+                       /* Power led off */
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x00);
+                       msleep(15);
+                       break;
+               }
+       }
        tm6000_v4l2_unregister(dev);
 
        tm6000_i2c_unregister(dev);
@@ -931,6 +942,9 @@ static void tm6000_usb_disconnect(struct usb_interface *interface)
 
        usb_put_dev(dev->udev);
 
+       tm6000_remove_from_devlist(dev);
+       tm6000_close_extension(dev);
+
        mutex_unlock(&dev->lock);
        kfree(dev);
 }
index bfbc53bd291217136c58ac5d9380e30e9945acab..c3690e3580da05a002ab272a042804dfda78886f 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
 #include "tm6000.h"
@@ -153,6 +154,22 @@ int tm6000_get_reg32 (struct tm6000_core *dev, u8 req, u16 value, u16 index)
        return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24;
 }
 
+int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep)
+{
+       int rc;
+
+       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
+       if (rc < 0)
+               return rc;
+
+       msleep(tsleep);
+
+       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+       msleep(tsleep);
+
+       return rc;
+}
+
 void tm6000_set_fourcc_format(struct tm6000_core *dev)
 {
        if (dev->dev_type == TM6010) {
@@ -323,6 +340,12 @@ int tm6000_init_analog_mode (struct tm6000_core *dev)
        tm6000_set_standard (dev, &dev->norm);
        tm6000_set_audio_bitrate (dev,48000);
 
+       /* switch dvb led off */
+       if (dev->gpio.dvb_led) {
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                       dev->gpio.dvb_led, 0x01);
+       }
+
        return 0;
 }
 
@@ -375,6 +398,13 @@ int tm6000_init_digital_mode (struct tm6000_core *dev)
                tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
                msleep(100);
        }
+
+       /* switch dvb led on */
+       if (dev->gpio.dvb_led) {
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                       dev->gpio.dvb_led, 0x00);
+       }
+
        return 0;
 }
 
@@ -600,3 +630,95 @@ printk("Original value=%d\n",val);
        return val;
 }
 EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate);
+
+static LIST_HEAD(tm6000_devlist);
+static DEFINE_MUTEX(tm6000_devlist_mutex);
+
+/*
+ * tm6000_realease_resource()
+ */
+
+void tm6000_remove_from_devlist(struct tm6000_core *dev)
+{
+       mutex_lock(&tm6000_devlist_mutex);
+       list_del(&dev->devlist);
+       mutex_unlock(&tm6000_devlist_mutex);
+};
+
+void tm6000_add_into_devlist(struct tm6000_core *dev)
+{
+       mutex_lock(&tm6000_devlist_mutex);
+       list_add_tail(&dev->devlist, &tm6000_devlist);
+       mutex_unlock(&tm6000_devlist_mutex);
+};
+
+/*
+ * Extension interface
+ */
+
+static LIST_HEAD(tm6000_extension_devlist);
+static DEFINE_MUTEX(tm6000_extension_devlist_lock);
+
+int tm6000_register_extension(struct tm6000_ops *ops)
+{
+       struct tm6000_core *dev = NULL;
+
+       mutex_lock(&tm6000_devlist_mutex);
+       mutex_lock(&tm6000_extension_devlist_lock);
+       list_add_tail(&ops->next, &tm6000_extension_devlist);
+       list_for_each_entry(dev, &tm6000_devlist, devlist) {
+               if (dev)
+                       ops->init(dev);
+       }
+       printk(KERN_INFO "tm6000: Initialized (%s) extension\n", ops->name);
+       mutex_unlock(&tm6000_extension_devlist_lock);
+       mutex_unlock(&tm6000_devlist_mutex);
+       return 0;
+}
+EXPORT_SYMBOL(tm6000_register_extension);
+
+void tm6000_unregister_extension(struct tm6000_ops *ops)
+{
+       struct tm6000_core *dev = NULL;
+
+       mutex_lock(&tm6000_devlist_mutex);
+       list_for_each_entry(dev, &tm6000_devlist, devlist) {
+               if (dev)
+                       ops->fini(dev);
+       }
+
+       mutex_lock(&tm6000_extension_devlist_lock);
+       printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
+       list_del(&ops->next);
+       mutex_unlock(&tm6000_extension_devlist_lock);
+       mutex_unlock(&tm6000_devlist_mutex);
+}
+EXPORT_SYMBOL(tm6000_unregister_extension);
+
+void tm6000_init_extension(struct tm6000_core *dev)
+{
+       struct tm6000_ops *ops = NULL;
+
+       mutex_lock(&tm6000_extension_devlist_lock);
+       if (!list_empty(&tm6000_extension_devlist)) {
+               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+                       if (ops->init)
+                               ops->init(dev);
+               }
+       }
+       mutex_unlock(&tm6000_extension_devlist_lock);
+}
+
+void tm6000_close_extension(struct tm6000_core *dev)
+{
+       struct tm6000_ops *ops = NULL;
+
+       mutex_lock(&tm6000_extension_devlist_lock);
+       if (!list_empty(&tm6000_extension_devlist)) {
+               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+                       if (ops->fini)
+                               ops->fini(dev);
+               }
+       }
+       mutex_unlock(&tm6000_extension_devlist_lock);
+}
index eafc89c22b6bec9982902b6584266bcd72c325e6..86c1c8b5f25aad41cc1bd82f7f62959493147538 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/usb.h>
 
 #include "tm6000.h"
@@ -28,6 +29,7 @@
 #include <media/tuner.h>
 
 #include "tuner-xc2028.h"
+#include "xc5000.h"
 
 static void inline print_err_status (struct tm6000_core *dev,
                                     int packet, int status)
@@ -100,7 +102,10 @@ int tm6000_start_stream(struct tm6000_core *dev)
 
        printk(KERN_INFO "tm6000: got start stream request %s\n",__FUNCTION__);
 
-       tm6000_init_digital_mode(dev);
+       if (dev->mode != TM6000_MODE_DIGITAL) {
+               tm6000_init_digital_mode(dev);
+               dev->mode = TM6000_MODE_DIGITAL;
+       }
 
        dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
        if(dvb->bulk_urb == NULL) {
@@ -254,27 +259,55 @@ int tm6000_dvb_register(struct tm6000_core *dev)
        dvb->adapter.priv = dev;
 
        if (dvb->frontend) {
-               struct xc2028_config cfg = {
-                       .i2c_adap = &dev->i2c_adap,
-                       .i2c_addr = dev->tuner_addr,
-               };
-
-               dvb->frontend->callback = tm6000_tuner_callback;
-               ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
-               if (ret < 0) {
-                       printk(KERN_ERR
-                               "tm6000: couldn't register frontend\n");
-                       goto adapter_err;
-               }
-
-               if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
-                       printk(KERN_ERR "tm6000: couldn't register "
-                                       "frontend (xc3028)\n");
-                       ret = -EINVAL;
-                       goto frontend_err;
+               switch (dev->tuner_type) {
+               case TUNER_XC2028: {
+                       struct xc2028_config cfg = {
+                               .i2c_adap = &dev->i2c_adap,
+                               .i2c_addr = dev->tuner_addr,
+                       };
+
+                       dvb->frontend->callback = tm6000_tuner_callback;
+                       ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+                       if (ret < 0) {
+                               printk(KERN_ERR
+                                       "tm6000: couldn't register frontend\n");
+                               goto adapter_err;
+                       }
+
+                       if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
+                               printk(KERN_ERR "tm6000: couldn't register "
+                                               "frontend (xc3028)\n");
+                               ret = -EINVAL;
+                               goto frontend_err;
+                       }
+                       printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
+                                        "attached to frontend!\n");
+                       break;
+                       }
+               case TUNER_XC5000: {
+                       struct xc5000_config cfg = {
+                               .i2c_address = dev->tuner_addr,
+                       };
+
+                       dvb->frontend->callback = tm6000_xc5000_callback;
+                       ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+                       if (ret < 0) {
+                               printk(KERN_ERR
+                                       "tm6000: couldn't register frontend\n");
+                               goto adapter_err;
+                       }
+
+                       if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
+                               printk(KERN_ERR "tm6000: couldn't register "
+                                               "frontend (xc5000)\n");
+                               ret = -EINVAL;
+                               goto frontend_err;
+                       }
+                       printk(KERN_INFO "tm6000: XC5000 asked to be "
+                                        "attached to frontend!\n");
+                       break;
+                       }
                }
-               printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
-                                "attached to frontend!\n");
        } else {
                printk(KERN_ERR "tm6000: no frontend found\n");
        }
index f2b7fe4a3581e5da6acd72ae040a66a5d35f6a72..56fa371e08c89e21c1b7eed1e3afd6ccad7b8820 100644 (file)
@@ -48,7 +48,7 @@
 #define TM6000_MIN_BUF 4
 #define TM6000_DEF_BUF 8
 
-#define TM6000_MAX_ISO_PACKETS 40      /* Max number of ISO packets */
+#define TM6000_MAX_ISO_PACKETS 46      /* Max number of ISO packets */
 
 /* Declare static vars that will be used as parameters */
 static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
@@ -205,7 +205,11 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp,
                c = (header >> 24) & 0xff;
 
                /* split the header fields */
-               size  = (((header & 0x7e) << 1) -1) *4;
+               size  = ((header & 0x7e) << 1);
+
+               if (size > 0)
+                       size -= 4;
+
                block = (header >> 7) & 0xf;
                field = (header >> 11) & 0x1;
                line  = (header >> 12) & 0x1ff;
@@ -307,10 +311,12 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp,
                case TM6000_URB_MSG_PTS:
                        break;
                case TM6000_URB_MSG_AUDIO:
-/* Need some code to process audio */
-printk ("%ld: cmd=%s, size=%d\n", jiffies,
+                       /* Need some code to process audio */
+                       printk ("%ld: cmd=%s, size=%d\n", jiffies,
                                tm6000_msg_type[cmd],size);
                        break;
+               case TM6000_URB_MSG_VBI:
+                       break;
                default:
                        dprintk (dev, V4L2_DEBUG_ISOC, "cmd=%s, size=%d\n",
                                                tm6000_msg_type[cmd],size);
@@ -333,14 +339,23 @@ printk ("%ld: cmd=%s, size=%d\n", jiffies,
        return rc;
 }
 
-static int copy_streams(u8 *data, u8 *out_p, unsigned long len,
-                       struct urb *urb, struct tm6000_buffer **buf)
+static int copy_streams(u8 *data, unsigned long len,
+                       struct urb *urb)
 {
        struct tm6000_dmaqueue  *dma_q = urb->context;
        struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
        u8 *ptr=data, *endp=data+len;
        unsigned long header=0;
        int rc=0;
+       struct tm6000_buffer *buf;
+       char *outp = NULL;
+
+       get_next_buf(dma_q, &buf);
+       if (buf)
+               outp = videobuf_to_vmalloc(&buf->vb);
+
+       if (!outp)
+               return 0;
 
        for (ptr=data; ptr<endp;) {
                if (!dev->isoc_ctl.cmd) {
@@ -388,14 +403,14 @@ static int copy_streams(u8 *data, u8 *out_p, unsigned long len,
                }
 HEADER:
                /* Copy or continue last copy */
-               rc=copy_packet(urb,header,&ptr,endp,out_p,buf);
+               rc=copy_packet(urb,header,&ptr,endp,outp,&buf);
                if (rc<0) {
                        buf=NULL;
                        printk(KERN_ERR "tm6000: buffer underrun at %ld\n",
                                        jiffies);
                        return rc;
                }
-               if (!*buf)
+               if (!buf)
                        return 0;
        }
 
@@ -404,31 +419,40 @@ HEADER:
 /*
  * Identify the tm5600/6000 buffer header type and properly handles
  */
-static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len,
-                       struct urb *urb, struct tm6000_buffer **buf)
+static int copy_multiplexed(u8 *ptr, unsigned long len,
+                       struct urb *urb)
 {
        struct tm6000_dmaqueue  *dma_q = urb->context;
        struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
        unsigned int pos=dev->isoc_ctl.pos,cpysize;
        int rc=1;
+       struct tm6000_buffer *buf;
+       char *outp = NULL;
+
+       get_next_buf(dma_q, &buf);
+       if (buf)
+               outp = videobuf_to_vmalloc(&buf->vb);
+
+       if (!outp)
+               return 0;
 
        while (len>0) {
-               cpysize=min(len,(*buf)->vb.size-pos);
-//printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos);
-               memcpy(&out_p[pos], ptr, cpysize);
+               cpysize=min(len,buf->vb.size-pos);
+               //printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos);
+               memcpy(&outp[pos], ptr, cpysize);
                pos+=cpysize;
                ptr+=cpysize;
                len-=cpysize;
-               if (pos >= (*buf)->vb.size) {
+               if (pos >= buf->vb.size) {
                        pos=0;
                        /* Announces that a new buffer were filled */
-                       buffer_filled (dev, dma_q, *buf);
+                       buffer_filled (dev, dma_q, buf);
                        dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n");
-                       get_next_buf (dma_q, buf);
-                       if (!*buf)
+                       get_next_buf (dma_q, &buf);
+                       if (!buf)
                                break;
-                       out_p = videobuf_to_vmalloc(&((*buf)->vb));
-                       if (!out_p)
+                       outp = videobuf_to_vmalloc(&(buf->vb));
+                       if (!outp)
                                return rc;
                        pos = 0;
                }
@@ -487,52 +511,36 @@ static inline int tm6000_isoc_copy(struct urb *urb)
        struct tm6000_dmaqueue  *dma_q = urb->context;
        struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
        struct tm6000_buffer *buf;
-       int i, len=0, rc=1;
-       int size;
-       char *outp = NULL, *p;
-       unsigned long copied;
-
-       get_next_buf(dma_q, &buf);
-       if (buf)
-               outp = videobuf_to_vmalloc(&buf->vb);
+       int i, len=0, rc=1, status;
+       char *p;
 
-       if (!outp)
-               return 0;
-
-       size = buf->vb.size;
-
-       copied=0;
-
-       if (urb->status<0) {
-               print_err_status (dev,-1,urb->status);
+       if (urb->status < 0) {
+               print_err_status (dev, -1, urb->status);
                return 0;
        }
 
        for (i = 0; i < urb->number_of_packets; i++) {
-               int status = urb->iso_frame_desc[i].status;
+               status = urb->iso_frame_desc[i].status;
 
                if (status<0) {
                        print_err_status (dev,i,status);
                        continue;
                }
 
-               len=urb->iso_frame_desc[i].actual_length;
+               len = urb->iso_frame_desc[i].actual_length;
 
-//             if (len>=TM6000_URB_MSG_LEN) {
-                       p=urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+               if (len > 0) {
+                       p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
                        if (!urb->iso_frame_desc[i].status) {
-                               if ((buf->fmt->fourcc)==V4L2_PIX_FMT_TM6000) {
-                                       rc=copy_multiplexed(p, outp, len, urb, &buf);
+                               if ((dev->fourcc)==V4L2_PIX_FMT_TM6000) {
+                                       rc=copy_multiplexed(p, len, urb);
                                        if (rc<=0)
                                                return rc;
                                } else {
-                                       copy_streams(p, outp, len, urb, &buf);
+                                       copy_streams(p, len, urb);
                                }
                        }
-                       copied += len;
-                       if (copied >= size || !buf)
-                               break;
-//             }
+               }
        }
        return rc;
 }
@@ -612,7 +620,7 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev)
 static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize)
 {
        struct tm6000_dmaqueue *dma_q = &dev->vidq;
-       int i, j, sb_size, pipe, size, max_packets, num_bufs = 5;
+       int i, j, sb_size, pipe, size, max_packets, num_bufs = 8;
        struct urb *urb;
 
        /* De-allocates all pending stuff */
index 6812d6867d578e5fde797935bbaf89db1b25e0fd..7bbaf26dea14f292b1808820698a702981514ebe 100644 (file)
@@ -168,6 +168,10 @@ struct tm6000_core {
        struct i2c_adapter              i2c_adap;
        struct i2c_client               i2c_client;
 
+
+       /* extension */
+       struct list_head                devlist;
+
        /* video for linux */
        int                             users;
 
@@ -203,6 +207,16 @@ struct tm6000_core {
        spinlock_t                   slock;
 };
 
+#define TM6000_AUDIO 0x10
+
+struct tm6000_ops {
+       struct list_head        next;
+       char                    *name;
+       int                     id;
+       int (*init)(struct tm6000_core *);
+       int (*fini)(struct tm6000_core *);
+};
+
 struct tm6000_fh {
        struct tm6000_core           *dev;
 
@@ -232,6 +246,8 @@ int tm6000_get_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index);
 int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index);
 int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index);
 int tm6000_set_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep);
+
 int tm6000_init (struct tm6000_core *dev);
 
 int tm6000_init_analog_mode (struct tm6000_core *dev);
@@ -246,6 +262,13 @@ int tm6000_v4l2_unregister(struct tm6000_core *dev);
 int tm6000_v4l2_exit(void);
 void tm6000_set_fourcc_format(struct tm6000_core *dev);
 
+void tm6000_remove_from_devlist(struct tm6000_core *dev);
+void tm6000_add_into_devlist(struct tm6000_core *dev);
+int tm6000_register_extension(struct tm6000_ops *ops);
+void tm6000_unregister_extension(struct tm6000_ops *ops);
+void tm6000_init_extension(struct tm6000_core *dev);
+void tm6000_close_extension(struct tm6000_core *dev);
+
 /* In tm6000-stds.c */
 void tm6000_get_std_res(struct tm6000_core *dev);
 int tm6000_set_standard (struct tm6000_core *dev, v4l2_std_id *norm);
@@ -275,7 +298,7 @@ unsigned int tm6000_v4l2_poll(struct file *file,
 int tm6000_queue_init(struct tm6000_core *dev);
 
 /* In tm6000-alsa.c */
-int tm6000_audio_init(struct tm6000_core *dev, int idx);
+/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/
 
 
 /* Debug stuff */
index 52408164036f3eda94b422d3b14898a26584c5f2..6a499f0eb5948426813f6a53acda1f5c6f243bd2 100644 (file)
@@ -378,47 +378,67 @@ int usbip_thread(void *param)
        complete_and_exit(&ut->thread_done, 0);
 }
 
+static void stop_rx_thread(struct usbip_device *ud)
+{
+       if (ud->tcp_rx.thread != NULL) {
+               send_sig(SIGKILL, ud->tcp_rx.thread, 1);
+               wait_for_completion(&ud->tcp_rx.thread_done);
+               usbip_udbg("rx_thread for ud %p has finished\n", ud);
+       }
+}
+
+static void stop_tx_thread(struct usbip_device *ud)
+{
+       if (ud->tcp_tx.thread != NULL) {
+               send_sig(SIGKILL, ud->tcp_tx.thread, 1);
+               wait_for_completion(&ud->tcp_tx.thread_done);
+               usbip_udbg("tx_thread for ud %p has finished\n", ud);
+       }
+}
+
 int usbip_start_threads(struct usbip_device *ud)
 {
        /*
         * threads are invoked per one device (per one connection).
         */
        struct task_struct *th;
+       int err = 0;
 
        th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");
        if (IS_ERR(th)) {
                printk(KERN_WARNING
                        "Unable to start control thread\n");
-               return PTR_ERR(th);
+               err = PTR_ERR(th);
+               goto ust_exit;
        }
+
        th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");
        if (IS_ERR(th)) {
                printk(KERN_WARNING
                        "Unable to start control thread\n");
-               return PTR_ERR(th);
+               err = PTR_ERR(th);
+               goto tx_thread_err;
        }
 
        /* confirm threads are starting */
        wait_for_completion(&ud->tcp_rx.thread_done);
        wait_for_completion(&ud->tcp_tx.thread_done);
+
        return 0;
+
+tx_thread_err:
+       stop_rx_thread(ud);
+
+ust_exit:
+       return err;
 }
 EXPORT_SYMBOL_GPL(usbip_start_threads);
 
 void usbip_stop_threads(struct usbip_device *ud)
 {
        /* kill threads related to this sdev, if v.c. exists */
-       if (ud->tcp_rx.thread != NULL) {
-               send_sig(SIGKILL, ud->tcp_rx.thread, 1);
-               wait_for_completion(&ud->tcp_rx.thread_done);
-               usbip_udbg("rx_thread for ud %p has finished\n", ud);
-       }
-
-       if (ud->tcp_tx.thread != NULL) {
-               send_sig(SIGKILL, ud->tcp_tx.thread, 1);
-               wait_for_completion(&ud->tcp_tx.thread_done);
-               usbip_udbg("tx_thread for ud %p has finished\n", ud);
-       }
+       stop_rx_thread(ud);
+       stop_tx_thread(ud);
 }
 EXPORT_SYMBOL_GPL(usbip_stop_threads);
 
index 0c82eb47a28dd706d554788533252231b3f6fe82..0f9ea58ff71705bb10823b83158ad99ae996c1d9 100644 (file)
@@ -523,7 +523,7 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image,
        }
 
        if (image->bus_resource.name == NULL) {
-               image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
+               image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC);
                if (image->bus_resource.name == NULL) {
                        dev_err(ca91cx42_bridge->parent, "Unable to allocate "
                                "memory for resource name\n");
index abe88a380b726894f82aae35158038e6a944d239..f09cac163139680a20eee6b9905c42ebce2b05f5 100644 (file)
@@ -828,7 +828,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
                return 0;
 
        if (image->bus_resource.name == NULL) {
-               image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
+               image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC);
                if (image->bus_resource.name == NULL) {
                        dev_err(tsi148_bridge->parent, "Unable to allocate "
                                "memory for resource name\n");
index b6fc2ca7d85c60b1eb9593c5db1f702f630b1b5b..3efcbf8afedfb019581f9cc978444351ce5c3145 100644 (file)
@@ -1,9 +1,11 @@
 config WLAGS49_H2
        tristate "Agere Systems HERMES II Wireless PC Card Model 0110"
-       depends on WLAN && WIRELESS_EXT && PCMCIA
+       depends on WLAN && PCMCIA
+       select WIRELESS_EXT
        select WEXT_SPY
+       select WEXT_PRIV
        ---help---
-         Driver for wireless cards using Agere's HERMES II chipset
-         which are identified with Manufacture ID: 0156,0003
-         The software is a modified version of wl_lkm_722_abg.tar.gz
-         from the Agere Systems website, addapted for Ubuntu 9.04.
+       Driver for wireless cards using Agere's HERMES II chipset
+       which are identified with Manufacture ID: 0156,0003
+       The software is a modified version of wl_lkm_722_abg.tar.gz
+       from the Agere Systems website, addapted for Ubuntu 9.04.
index 48c44c8fdb28e9e3470f72086f6eb40a2451cf2e..26cf5486edd61462028176c952afddf3e81f9b54 100644 (file)
@@ -62,6 +62,7 @@
 /*******************************************************************************
  *  include files
  ******************************************************************************/
+#include <linux/string.h>
 #include <wl_version.h>
 
 #include <debug.h>
index 6d96d03cf4909877f89936f1571b6efadfad3665..fa658c38001e6e7e6bce3cfd68dfa5c54f3996d7 100644 (file)
@@ -2,6 +2,6 @@
 extern void register_wlags_sysfs(struct net_device *);
 extern void unregister_wlags_sysfs(struct net_device *);
 #else
-static void register_wlags_sysfs(struct net_device *) { return; };
-static void unregister_wlags_sysfs(struct net_device *) { return; };
+static inline void register_wlags_sysfs(struct net_device *net) { }
+static inline void unregister_wlags_sysfs(struct net_device *net) { }
 #endif
index dcc170929c13729827369108ea8c0e14a5f2c087..bf5664a51cd4aaef06fd11965a76d2fd09860989 100644 (file)
@@ -1,9 +1,11 @@
 config WLAGS49_H25
        tristate "Linksys HERMES II.5 WCF54G_Wireless-G_CompactFlash_Card"
-       depends on WLAN && WIRELESS_EXT && PCMCIA
+       depends on WLAN && PCMCIA
+       select WIRELESS_EXT
        select WEXT_SPY
+       select WEXT_PRIV
        ---help---
-         Driver for wireless cards using Agere's HERMES II.5 chipset
-         which are identified with Manufacture ID: 0156,0004
-         The software is a modified version of wl_lkm_722_abg.tar.gz
-         from the Agere Systems website, addapted for Ubuntu 9.04.
+       Driver for wireless cards using Agere's HERMES II.5 chipset
+       which are identified with Manufacture ID: 0156,0004
+       The software is a modified version of wl_lkm_722_abg.tar.gz
+       from the Agere Systems website, addapted for Ubuntu 9.04.
diff --git a/drivers/staging/xgifb/Kconfig b/drivers/staging/xgifb/Kconfig
new file mode 100644 (file)
index 0000000..bb0ca59
--- /dev/null
@@ -0,0 +1,11 @@
+config FB_XGI
+       tristate "XGI display support"
+       depends on FB && PCI
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This driver supports notebooks with XGI Z7,Z9,Z11 PCI chips.
+         Say Y if you have such a graphics card.
+         To compile this driver as a module, choose M here: the
+         module will be called xgifb.ko
diff --git a/drivers/staging/xgifb/Makefile b/drivers/staging/xgifb/Makefile
new file mode 100644 (file)
index 0000000..2a31770
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_FB_XGI)  += xgifb.o
+
+xgifb-objs := XGI_main_26.o XGI_accel.o vb_init.o vb_setmode.o vb_util.o vb_ext.o
+
diff --git a/drivers/staging/xgifb/TODO b/drivers/staging/xgifb/TODO
new file mode 100644 (file)
index 0000000..7d71019
--- /dev/null
@@ -0,0 +1,15 @@
+This drivers still need a lot of work. I can list all cleanups to do but it's
+going to be long. So, I'm writing "cleanups" and not the list.
+
+Arnaud
+
+TODO:
+- clean ups
+- fix build warnings when module
+- sort out dup ids with SiS driver
+- remove useless/wrong/unused #ifdef/code/...
+- fix printk usages
+- get rid of non-linux related stuff
+
+Please send patches to:
+Arnaud Patard <apatard@mandriva.com>
diff --git a/drivers/staging/xgifb/XGI.h b/drivers/staging/xgifb/XGI.h
new file mode 100644 (file)
index 0000000..87803dd
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _XGI_H
+#define _XGI_H
+
+#if 1
+#define TWDEBUG(x)
+#else
+#define TWDEBUG(x) printk(KERN_INFO x "\n");
+#endif
+
+#endif
diff --git a/drivers/staging/xgifb/XGI_accel.c b/drivers/staging/xgifb/XGI_accel.c
new file mode 100644 (file)
index 0000000..86ec342
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+ * XGI 300/630/730/540/315/550/650/740 frame buffer driver
+ * for Linux kernels 2.4.x and 2.5.x
+ *
+ * 2D acceleration part
+ *
+ * Based on the X driver's XGI300_accel.c which is
+ *     Copyright Xavier Ducoin <x.ducoin@lectra.com>
+ *     Copyright 2002 by Thomas Winischhofer, Vienna, Austria
+ * and XGI310_accel.c which is
+ *     Copyright 2002 by Thomas Winischhofer, Vienna, Austria
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *                     (see http://www.winischhofer.net/
+ *                     for more information and updates)
+ */
+
+//#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vt_kern.h>
+#include <linux/capability.h>
+#include <linux/fs.h>
+#include <linux/agp_backend.h>
+
+#include <linux/types.h>
+/*
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <linux/XGIfb.h>
+#else
+#include <video/XGIfb.h>
+#endif
+*/
+#include <asm/io.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+#endif
+
+#include "osdef.h"
+#include "vgatypes.h"
+#include "vb_struct.h"
+#include "XGIfb.h"
+#include "XGI_accel.h"
+
+
+extern struct     video_info xgi_video_info;
+extern int XGIfb_accel;
+
+static const int XGIALUConv[] =
+{
+    0x00,       /* dest = 0;            0,      GXclear,        0 */
+    0x88,       /* dest &= src;         DSa,    GXand,          0x1 */
+    0x44,       /* dest = src & ~dest;  SDna,   GXandReverse,   0x2 */
+    0xCC,       /* dest = src;          S,      GXcopy,         0x3 */
+    0x22,       /* dest &= ~src;        DSna,   GXandInverted,  0x4 */
+    0xAA,       /* dest = dest;         D,      GXnoop,         0x5 */
+    0x66,       /* dest = ^src;         DSx,    GXxor,          0x6 */
+    0xEE,       /* dest |= src;         DSo,    GXor,           0x7 */
+    0x11,       /* dest = ~src & ~dest; DSon,   GXnor,          0x8 */
+    0x99,       /* dest ^= ~src ;       DSxn,   GXequiv,        0x9 */
+    0x55,       /* dest = ~dest;        Dn,     GXInvert,       0xA */
+    0xDD,       /* dest = src|~dest ;   SDno,   GXorReverse,    0xB */
+    0x33,       /* dest = ~src;         Sn,     GXcopyInverted, 0xC */
+    0xBB,       /* dest |= ~src;        DSno,   GXorInverted,   0xD */
+    0x77,       /* dest = ~src|~dest;   DSan,   GXnand,         0xE */
+    0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
+};
+/* same ROP but with Pattern as Source */
+static const int XGIPatALUConv[] =
+{
+    0x00,       /* dest = 0;            0,      GXclear,        0 */
+    0xA0,       /* dest &= src;         DPa,    GXand,          0x1 */
+    0x50,       /* dest = src & ~dest;  PDna,   GXandReverse,   0x2 */
+    0xF0,       /* dest = src;          P,      GXcopy,         0x3 */
+    0x0A,       /* dest &= ~src;        DPna,   GXandInverted,  0x4 */
+    0xAA,       /* dest = dest;         D,      GXnoop,         0x5 */
+    0x5A,       /* dest = ^src;         DPx,    GXxor,          0x6 */
+    0xFA,       /* dest |= src;         DPo,    GXor,           0x7 */
+    0x05,       /* dest = ~src & ~dest; DPon,   GXnor,          0x8 */
+    0xA5,       /* dest ^= ~src ;       DPxn,   GXequiv,        0x9 */
+    0x55,       /* dest = ~dest;        Dn,     GXInvert,       0xA */
+    0xF5,       /* dest = src|~dest ;   PDno,   GXorReverse,    0xB */
+    0x0F,       /* dest = ~src;         Pn,     GXcopyInverted, 0xC */
+    0xAF,       /* dest |= ~src;        DPno,   GXorInverted,   0xD */
+    0x5F,       /* dest = ~src|~dest;   DPan,   GXnand,         0xE */
+    0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
+};
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
+static const unsigned char myrops[] = {
+       3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
+   };
+#endif
+
+/* 300 series */
+#if 0
+static void
+XGI300Sync(void)
+{
+       XGI300Idle
+}
+#endif
+static void
+XGI310Sync(void)
+{
+       XGI310Idle
+}
+#if 0
+static void
+XGI300SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
+                                unsigned int planemask, int trans_color)
+{
+       XGI300SetupDSTColorDepth(xgi_video_info.DstColor);
+       XGI300SetupSRCPitch(xgi_video_info.video_linelength)
+       XGI300SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
+
+       if(trans_color != -1) {
+               XGI300SetupROP(0x0A)
+               XGI300SetupSRCTrans(trans_color)
+               XGI300SetupCMDFlag(TRANSPARENT_BITBLT)
+       } else {
+               XGI300SetupROP(XGIALUConv[rop])
+       }
+       if(xdir > 0) {
+               XGI300SetupCMDFlag(X_INC)
+       }
+       if(ydir > 0) {
+               XGI300SetupCMDFlag(Y_INC)
+       }
+}
+
+static void
+XGI300SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
+                                int width, int height)
+{
+       long srcbase, dstbase;
+
+       srcbase = dstbase = 0;
+       if (src_y >= 2048) {
+               srcbase = xgi_video_info.video_linelength * src_y;
+               src_y = 0;
+       }
+       if (dst_y >= 2048) {
+               dstbase = xgi_video_info.video_linelength * dst_y;
+               dst_y = 0;
+       }
+
+       XGI300SetupSRCBase(srcbase);
+       XGI300SetupDSTBase(dstbase);
+
+       if(!(xgi_video_info.CommandReg & X_INC))  {
+               src_x += width-1;
+               dst_x += width-1;
+       }
+       if(!(xgi_video_info.CommandReg & Y_INC))  {
+               src_y += height-1;
+               dst_y += height-1;
+       }
+       XGI300SetupRect(width, height)
+       XGI300SetupSRCXY(src_x, src_y)
+       XGI300SetupDSTXY(dst_x, dst_y)
+       XGI300DoCMD
+}
+
+static void
+XGI300SetupForSolidFill(int color, int rop, unsigned int planemask)
+{
+       XGI300SetupPATFG(color)
+       XGI300SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
+       XGI300SetupDSTColorDepth(xgi_video_info.DstColor);
+       XGI300SetupROP(XGIPatALUConv[rop])
+       XGI300SetupCMDFlag(PATFG)
+}
+
+static void
+XGI300SubsequentSolidFillRect(int x, int y, int w, int h)
+{
+       long dstbase;
+
+       dstbase = 0;
+       if(y >= 2048) {
+               dstbase = xgi_video_info.video_linelength * y;
+               y = 0;
+       }
+       XGI300SetupDSTBase(dstbase)
+       XGI300SetupDSTXY(x,y)
+       XGI300SetupRect(w,h)
+       XGI300SetupCMDFlag(X_INC | Y_INC | BITBLT)
+       XGI300DoCMD
+}
+#endif
+/* 310/325 series ------------------------------------------------ */
+
+static void
+XGI310SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
+                                unsigned int planemask, int trans_color)
+{
+       XGI310SetupDSTColorDepth(xgi_video_info.DstColor);
+       XGI310SetupSRCPitch(xgi_video_info.video_linelength)
+       XGI310SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
+       if (trans_color != -1) {
+               XGI310SetupROP(0x0A)
+               XGI310SetupSRCTrans(trans_color)
+               XGI310SetupCMDFlag(TRANSPARENT_BITBLT)
+       } else {
+               XGI310SetupROP(XGIALUConv[rop])
+               /* Set command - not needed, both 0 */
+               /* XGISetupCMDFlag(BITBLT | SRCVIDEO) */
+       }
+       XGI310SetupCMDFlag(xgi_video_info.XGI310_AccelDepth)
+       /* TW: The 310/325 series is smart enough to know the direction */
+}
+
+static void
+XGI310SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
+                                int width, int height)
+{
+       long srcbase, dstbase;
+       int mymin, mymax;
+
+       srcbase = dstbase = 0;
+       mymin = min(src_y, dst_y);
+       mymax = max(src_y, dst_y);
+
+       /* Although the chip knows the direction to use
+        * if the source and destination areas overlap,
+        * that logic fails if we fiddle with the bitmap
+        * addresses. Therefore, we check if the source
+        * and destination blitting areas overlap and
+        * adapt the bitmap addresses synchronously
+        * if the coordinates exceed the valid range.
+        * The the areas do not overlap, we do our
+        * normal check.
+        */
+       if((mymax - mymin) < height) {
+          if((src_y >= 2048) || (dst_y >= 2048)) {
+             srcbase = xgi_video_info.video_linelength * mymin;
+             dstbase = xgi_video_info.video_linelength * mymin;
+             src_y -= mymin;
+             dst_y -= mymin;
+          }
+       } else {
+          if(src_y >= 2048) {
+             srcbase = xgi_video_info.video_linelength * src_y;
+             src_y = 0;
+          }
+          if(dst_y >= 2048) {
+             dstbase = xgi_video_info.video_linelength * dst_y;
+             dst_y = 0;
+          }
+       }
+
+       XGI310SetupSRCBase(srcbase);
+       XGI310SetupDSTBase(dstbase);
+       XGI310SetupRect(width, height)
+       XGI310SetupSRCXY(src_x, src_y)
+       XGI310SetupDSTXY(dst_x, dst_y)
+       XGI310DoCMD
+}
+
+static void
+XGI310SetupForSolidFill(int color, int rop, unsigned int planemask)
+{
+       XGI310SetupPATFG(color)
+       XGI310SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
+       XGI310SetupDSTColorDepth(xgi_video_info.DstColor);
+       XGI310SetupROP(XGIPatALUConv[rop])
+       XGI310SetupCMDFlag(PATFG | xgi_video_info.XGI310_AccelDepth)
+}
+
+static void
+XGI310SubsequentSolidFillRect(int x, int y, int w, int h)
+{
+       long dstbase;
+
+       dstbase = 0;
+       if(y >= 2048) {
+               dstbase = xgi_video_info.video_linelength * y;
+               y = 0;
+       }
+       XGI310SetupDSTBase(dstbase)
+       XGI310SetupDSTXY(x,y)
+       XGI310SetupRect(w,h)
+       XGI310SetupCMDFlag(BITBLT)
+       XGI310DoCMD
+}
+
+/* --------------------------------------------------------------------- */
+
+/* The exported routines */
+
+int XGIfb_initaccel(void)
+{
+#ifdef XGIFB_USE_SPINLOCKS
+    spin_lock_init(&xgi_video_info.lockaccel);
+#endif
+    return(0);
+}
+
+void XGIfb_syncaccel(void)
+{
+
+    XGI310Sync();
+
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)  /* --- KERNEL 2.5.34 and later --- */
+
+int fbcon_XGI_sync(struct fb_info *info)
+{
+    if(!XGIfb_accel) return 0;
+    CRITFLAGS
+
+    XGI310Sync();
+
+   CRITEND
+   return 0;
+}
+
+void fbcon_XGI_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+   int col=0;
+   CRITFLAGS
+
+
+   if(!rect->width || !rect->height)
+       return;
+
+   if(!XGIfb_accel) {
+       cfb_fillrect(info, rect);
+       return;
+   }
+
+   switch(info->var.bits_per_pixel) {
+               case 8: col = rect->color;
+                       break;
+               case 16: col = ((u32 *)(info->pseudo_palette))[rect->color];
+                        break;
+               case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
+                        break;
+       }
+
+
+          CRITBEGIN
+          XGI310SetupForSolidFill(col, myrops[rect->rop], 0);
+          XGI310SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
+          CRITEND
+          XGI310Sync();
+
+
+}
+
+void fbcon_XGI_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+   int xdir, ydir;
+   CRITFLAGS
+
+
+   if(!XGIfb_accel) {
+       cfb_copyarea(info, area);
+       return;
+   }
+
+   if(!area->width || !area->height)
+       return;
+
+   if(area->sx < area->dx) xdir = 0;
+   else                    xdir = 1;
+   if(area->sy < area->dy) ydir = 0;
+   else                    ydir = 1;
+
+      CRITBEGIN
+      XGI310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
+      XGI310SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
+      CRITEND
+      XGI310Sync();
+
+}
+
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)  /* ------ KERNEL <2.5.34 ------ */
+
+void fbcon_XGI_bmove(struct display *p, int srcy, int srcx,
+                           int dsty, int dstx, int height, int width)
+{
+        int xdir, ydir;
+       CRITFLAGS
+
+       if(!xgi_video_info.accel) {
+           switch(xgi_video_info.video_bpp) {
+           case 8:
+#ifdef FBCON_HAS_CFB8
+              fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width);
+#endif
+              break;
+           case 16:
+#ifdef FBCON_HAS_CFB16
+              fbcon_cfb16_bmove(p, srcy, srcx, dsty, dstx, height, width);
+#endif
+              break;
+           case 32:
+#ifdef FBCON_HAS_CFB32
+              fbcon_cfb32_bmove(p, srcy, srcx, dsty, dstx, height, width);
+#endif
+              break;
+            }
+           return;
+       }
+
+       srcx *= fontwidth(p);
+       srcy *= fontheight(p);
+       dstx *= fontwidth(p);
+       dsty *= fontheight(p);
+       width *= fontwidth(p);
+       height *= fontheight(p);
+
+       if(srcx < dstx) xdir = 0;
+       else            xdir = 1;
+       if(srcy < dsty) ydir = 0;
+       else            ydir = 1;
+
+
+          CRITBEGIN
+          XGI310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
+          XGI310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
+          CRITEND
+          XGI310Sync();
+#if 0
+          printk(KERN_INFO "XGI_bmove sx %d sy %d dx %d dy %d w %d h %d\n",
+               srcx, srcy, dstx, dsty, width, height);
+#endif
+
+}
+
+
+static void fbcon_XGI_clear(struct vc_data *conp, struct display *p,
+                       int srcy, int srcx, int height, int width, int color)
+{
+       CRITFLAGS
+
+       srcx *= fontwidth(p);
+       srcy *= fontheight(p);
+       width *= fontwidth(p);
+       height *= fontheight(p);
+
+
+          CRITBEGIN
+          XGI310SetupForSolidFill(color, 3, 0);
+          XGI310SubsequentSolidFillRect(srcx, srcy, width, height);
+          CRITEND
+          XGI310Sync();
+
+}
+
+void fbcon_XGI_clear8(struct vc_data *conp, struct display *p,
+                       int srcy, int srcx, int height, int width)
+{
+       u32 bgx;
+
+       if(!xgi_video_info.accel) {
+#ifdef FBCON_HAS_CFB8
+           fbcon_cfb8_clear(conp, p, srcy, srcx, height, width);
+#endif
+           return;
+       }
+
+       bgx = attr_bgcol_ec(p, conp);
+       fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx);
+}
+
+void fbcon_XGI_clear16(struct vc_data *conp, struct display *p,
+                       int srcy, int srcx, int height, int width)
+{
+       u32 bgx;
+       if(!xgi_video_info.accel) {
+#ifdef FBCON_HAS_CFB16
+           fbcon_cfb16_clear(conp, p, srcy, srcx, height, width);
+#endif
+           return;
+       }
+
+       bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+       fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx);
+}
+
+void fbcon_XGI_clear32(struct vc_data *conp, struct display *p,
+                       int srcy, int srcx, int height, int width)
+{
+       u32 bgx;
+
+       if(!xgi_video_info.accel) {
+#ifdef FBCON_HAS_CFB32
+           fbcon_cfb32_clear(conp, p, srcy, srcx, height, width);
+#endif
+           return;
+       }
+
+       bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+       fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx);
+}
+
+void fbcon_XGI_revc(struct display *p, int srcx, int srcy)
+{
+       CRITFLAGS
+
+       if(!xgi_video_info.accel) {
+           switch(xgi_video_info.video_bpp) {
+           case 16:
+#ifdef FBCON_HAS_CFB16
+              fbcon_cfb16_revc(p, srcx, srcy);
+#endif
+              break;
+           case 32:
+#ifdef FBCON_HAS_CFB32
+              fbcon_cfb32_revc(p, srcx, srcy);
+#endif
+              break;
+            }
+           return;
+       }
+
+       srcx *= fontwidth(p);
+       srcy *= fontheight(p);
+
+
+          CRITBEGIN
+          XGI310SetupForSolidFill(0, 0x0a, 0);
+          XGI310SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p));
+          CRITEND
+          XGI310Sync();
+
+}
+
+#ifdef FBCON_HAS_CFB8
+struct display_switch fbcon_XGI8 = {
+       setup:                  fbcon_cfb8_setup,
+       bmove:                  fbcon_XGI_bmove,
+       clear:                  fbcon_XGI_clear8,
+       putc:                   fbcon_cfb8_putc,
+       putcs:                  fbcon_cfb8_putcs,
+       revc:                   fbcon_cfb8_revc,
+       clear_margins:          fbcon_cfb8_clear_margins,
+       fontwidthmask:          FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB16
+struct display_switch fbcon_XGI16 = {
+       setup:                  fbcon_cfb16_setup,
+       bmove:                  fbcon_XGI_bmove,
+       clear:                  fbcon_XGI_clear16,
+       putc:                   fbcon_cfb16_putc,
+       putcs:                  fbcon_cfb16_putcs,
+       revc:                   fbcon_XGI_revc,
+       clear_margins:          fbcon_cfb16_clear_margins,
+       fontwidthmask:          FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB32
+struct display_switch fbcon_XGI32 = {
+       setup:                  fbcon_cfb32_setup,
+       bmove:                  fbcon_XGI_bmove,
+       clear:                  fbcon_XGI_clear32,
+       putc:                   fbcon_cfb32_putc,
+       putcs:                  fbcon_cfb32_putcs,
+       revc:                   fbcon_XGI_revc,
+       clear_margins:          fbcon_cfb32_clear_margins,
+       fontwidthmask:          FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+
+#endif /* KERNEL VERSION */
+
+
diff --git a/drivers/staging/xgifb/XGI_accel.h b/drivers/staging/xgifb/XGI_accel.h
new file mode 100644 (file)
index 0000000..04e1267
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * XGI 300/630/730/540/315/550/650/740 frame buffer driver
+ * for Linux kernels 2.4.x and 2.5.x
+ *
+ * 2D acceleration part
+ *
+ * Based on the X driver's XGI300_accel.h which is
+ *     Copyright Xavier Ducoin <x.ducoin@lectra.com>
+ *     Copyright 2002 by Thomas Winischhofer, Vienna, Austria
+ * and XGI310_accel.h which is
+ *     Copyright 2002 by Thomas Winischhofer, Vienna, Austria
+ *
+ * Author:   Thomas Winischhofer <thomas@winischhofer.net>:
+ *                     (see http://www.winischhofer.net/
+ *                     for more information and updates)
+ */
+
+#ifndef _XGIFB_ACCEL_H
+#define _XGIFB_ACCEL_H
+
+/* Guard accelerator accesses with spin_lock_irqsave? Works well without. */
+#undef XGIFB_USE_SPINLOCKS
+
+#ifdef XGIFB_USE_SPINLOCKS
+#include <linux/spinlock.h>
+#define CRITBEGIN  spin_lock_irqsave(&xgi_video_info.lockaccel), critflags);
+#define CRITEND           spin_unlock_irqrestore(&xgi_video_info.lockaccel), critflags);
+#define CRITFLAGS  unsigned long critflags;
+#else
+#define CRITBEGIN
+#define CRITEND
+#define CRITFLAGS
+#endif
+
+/* Definitions for the XGI engine communication. */
+
+#define PATREGSIZE      384  /* Pattern register size. 384 bytes @ 0x8300 */
+#define BR(x)   (0x8200 | (x) << 2)
+#define PBR(x)  (0x8300 | (x) << 2)
+
+/* XGI300 engine commands */
+#define BITBLT                  0x00000000  /* Blit */
+#define COLOREXP                0x00000001  /* Color expand */
+#define ENCOLOREXP              0x00000002  /* Enhanced color expand */
+#define MULTIPLE_SCANLINE       0x00000003  /* ? */
+#define LINE                    0x00000004  /* Draw line */
+#define TRAPAZOID_FILL          0x00000005  /* Fill trapezoid */
+#define TRANSPARENT_BITBLT      0x00000006  /* Transparent Blit */
+
+/* Additional engine commands for 310/325 */
+#define ALPHA_BLEND            0x00000007  /* Alpha blend ? */
+#define A3D_FUNCTION           0x00000008  /* 3D command ? */
+#define        CLEAR_Z_BUFFER          0x00000009  /* ? */
+#define GRADIENT_FILL          0x0000000A  /* Gradient fill */
+#define STRETCH_BITBLT         0x0000000B  /* Stretched Blit */
+
+/* source select */
+#define SRCVIDEO                0x00000000  /* source is video RAM */
+#define SRCSYSTEM               0x00000010  /* source is system memory */
+#define SRCCPUBLITBUF           SRCSYSTEM   /* source is CPU-driven BitBuffer (for color expand) */
+#define SRCAGP                  0x00000020  /* source is AGP memory (?) */
+
+/* Pattern flags */
+#define PATFG                   0x00000000  /* foreground color */
+#define PATPATREG               0x00000040  /* pattern in pattern buffer (0x8300) */
+#define PATMONO                 0x00000080  /* mono pattern */
+
+/* blitting direction (300 series only) */
+#define X_INC                   0x00010000
+#define X_DEC                   0x00000000
+#define Y_INC                   0x00020000
+#define Y_DEC                   0x00000000
+
+/* Clipping flags */
+#define NOCLIP                  0x00000000
+#define NOMERGECLIP             0x04000000
+#define CLIPENABLE              0x00040000
+#define CLIPWITHOUTMERGE        0x04040000
+
+/* Transparency */
+#define OPAQUE                  0x00000000
+#define TRANSPARENT             0x00100000
+
+/* ? */
+#define DSTAGP                  0x02000000
+#define DSTVIDEO                0x02000000
+
+/* Line */
+#define LINE_STYLE              0x00800000
+#define NO_RESET_COUNTER        0x00400000
+#define NO_LAST_PIXEL           0x00200000
+
+/* Subfunctions for Color/Enhanced Color Expansion (310/325 only) */
+#define COLOR_TO_MONO          0x00100000
+#define AA_TEXT                        0x00200000
+
+/* Some general registers for 310/325 series */
+#define SRC_ADDR               0x8200
+#define SRC_PITCH              0x8204
+#define AGP_BASE               0x8206 /* color-depth dependent value */
+#define SRC_Y                  0x8208
+#define SRC_X                  0x820A
+#define DST_Y                  0x820C
+#define DST_X                  0x820E
+#define DST_ADDR               0x8210
+#define DST_PITCH              0x8214
+#define DST_HEIGHT             0x8216
+#define RECT_WIDTH             0x8218
+#define RECT_HEIGHT            0x821A
+#define PAT_FGCOLOR            0x821C
+#define PAT_BGCOLOR            0x8220
+#define SRC_FGCOLOR            0x8224
+#define SRC_BGCOLOR            0x8228
+#define MONO_MASK              0x822C
+#define LEFT_CLIP              0x8234
+#define TOP_CLIP               0x8236
+#define RIGHT_CLIP             0x8238
+#define BOTTOM_CLIP            0x823A
+#define COMMAND_READY          0x823C
+#define FIRE_TRIGGER           0x8240
+
+#define PATTERN_REG            0x8300  /* 384 bytes pattern buffer */
+
+/* Line registers */
+#define LINE_X0                        SRC_Y
+#define LINE_X1                        DST_Y
+#define LINE_Y0                        SRC_X
+#define LINE_Y1                        DST_X
+#define LINE_COUNT             RECT_WIDTH
+#define LINE_STYLE_PERIOD      RECT_HEIGHT
+#define LINE_STYLE_0           MONO_MASK
+#define LINE_STYLE_1           0x8230
+#define LINE_XN                        PATTERN_REG
+#define LINE_YN                        PATTERN_REG+2
+
+/* Transparent bitblit registers */
+#define TRANS_DST_KEY_HIGH     PAT_FGCOLOR
+#define TRANS_DST_KEY_LOW      PAT_BGCOLOR
+#define TRANS_SRC_KEY_HIGH     SRC_FGCOLOR
+#define TRANS_SRC_KEY_LOW      SRC_BGCOLOR
+
+/* Queue */
+#define Q_BASE_ADDR            0x85C0  /* Base address of software queue (?) */
+#define Q_WRITE_PTR            0x85C4  /* Current write pointer (?) */
+#define Q_READ_PTR             0x85C8  /* Current read pointer (?) */
+#define Q_STATUS               0x85CC  /* queue status */
+
+
+#define MMIO_IN8(base, offset) \
+       *(volatile u8 *)(((u8*)(base)) + (offset))
+#define MMIO_IN16(base, offset) \
+       *(volatile u16 *)(void *)(((u8*)(base)) + (offset))
+#define MMIO_IN32(base, offset) \
+       *(volatile u32 *)(void *)(((u8*)(base)) + (offset))
+#define MMIO_OUT8(base, offset, val) \
+       *(volatile u8 *)(((u8*)(base)) + (offset)) = (val)
+#define MMIO_OUT16(base, offset, val) \
+       *(volatile u16 *)(void *)(((u8*)(base)) + (offset)) = (val)
+#define MMIO_OUT32(base, offset, val) \
+       *(volatile u32 *)(void *)(((u8*)(base)) + (offset)) = (val)
+
+
+
+/* ------------- XGI 300 series -------------- */
+
+/* Macros to do useful things with the XGI BitBLT engine */
+
+/* BR(16) (0x8420):
+
+   bit 31 2D engine: 1 is idle,
+   bit 30 3D engine: 1 is idle,
+   bit 29 Command queue: 1 is empty
+
+   bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0]
+
+   bits 15:0:  Current command queue length
+
+*/
+
+/* TW: BR(16)+2 = 0x8242 */
+
+int     xgiCmdQueLen;
+
+#define XGI300Idle \
+  { \
+  while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  xgiCmdQueLen=MMIO_IN16(xgi_video_info.mmio_vbase, 0x8240); \
+  }
+/* TW: (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
+
+#define XGI300SetupSRCBase(base) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(0), base);\
+                xgiCmdQueLen --;
+
+#define XGI300SetupSRCPitch(pitch) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT16(xgi_video_info.mmio_vbase, BR(1), pitch);\
+                xgiCmdQueLen --;
+
+#define XGI300SetupSRCXY(x,y) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(2), (x)<<16 | (y) );\
+                xgiCmdQueLen --;
+
+#define XGI300SetupDSTBase(base) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(4), base);\
+                xgiCmdQueLen --;
+
+#define XGI300SetupDSTXY(x,y) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(3), (x)<<16 | (y) );\
+                xgiCmdQueLen --;
+
+#define XGI300SetupDSTRect(x,y) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(5), (y)<<16 | (x) );\
+                xgiCmdQueLen --;
+
+#define XGI300SetupDSTColorDepth(bpp) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT16(xgi_video_info.mmio_vbase, BR(1)+2, bpp);\
+                xgiCmdQueLen --;
+
+#define XGI300SetupRect(w,h) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(6), (h)<<16 | (w) );\
+                xgiCmdQueLen --;
+
+#define XGI300SetupPATFG(color) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(7), color);\
+                xgiCmdQueLen --;
+
+#define XGI300SetupPATBG(color) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(8), color);\
+                xgiCmdQueLen --;
+
+#define XGI300SetupSRCFG(color) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(9), color);\
+                xgiCmdQueLen --;
+
+#define XGI300SetupSRCBG(color) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(10), color);\
+                xgiCmdQueLen --;
+
+/* 0x8224 src colorkey high */
+/* 0x8228 src colorkey low */
+/* 0x821c dest colorkey high */
+/* 0x8220 dest colorkey low */
+#define XGI300SetupSRCTrans(color) \
+                if (xgiCmdQueLen <= 1)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8224, color);\
+               MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8228, color);\
+               xgiCmdQueLen -= 2;
+
+#define XGI300SetupDSTTrans(color) \
+               if (xgiCmdQueLen <= 1)  XGI300Idle;\
+               MMIO_OUT32(xgi_video_info.mmio_vbase, 0x821C, color); \
+               MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8220, color); \
+                xgiCmdQueLen -= 2;
+
+#define XGI300SetupMONOPAT(p0,p1) \
+                if (xgiCmdQueLen <= 1)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(11), p0);\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(12), p1);\
+                xgiCmdQueLen -= 2;
+
+#define XGI300SetupClipLT(left,top) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
+                xgiCmdQueLen--;
+
+#define XGI300SetupClipRB(right,bottom) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
+                xgiCmdQueLen--;
+
+/* General */
+#define XGI300SetupROP(rop) \
+                xgi_video_info.CommandReg = (rop) << 8;
+
+#define XGI300SetupCMDFlag(flags) \
+                xgi_video_info.CommandReg |= (flags);
+
+#define XGI300DoCMD \
+                if (xgiCmdQueLen <= 1)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(15), xgi_video_info.CommandReg); \
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(16), 0);\
+                xgiCmdQueLen -= 2;
+
+/* Line */
+#define XGI300SetupX0Y0(x,y) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(2), (y)<<16 | (x) );\
+                xgiCmdQueLen--;
+
+#define XGI300SetupX1Y1(x,y) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(3), (y)<<16 | (x) );\
+                xgiCmdQueLen--;
+
+#define XGI300SetupLineCount(c) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT16(xgi_video_info.mmio_vbase, BR(6), c);\
+                xgiCmdQueLen--;
+
+#define XGI300SetupStylePeriod(p) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT16(xgi_video_info.mmio_vbase, BR(6)+2, p);\
+                xgiCmdQueLen--;
+
+#define XGI300SetupStyleLow(ls) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(11), ls);\
+                xgiCmdQueLen--;
+
+#define XGI300SetupStyleHigh(ls) \
+                if (xgiCmdQueLen <= 0)  XGI300Idle;\
+                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(12), ls);\
+                xgiCmdQueLen--;
+
+
+
+/* ----------- XGI 310/325 series --------------- */
+
+/* Q_STATUS:
+   bit 31 = 1: All engines idle and all queues empty
+   bit 30 = 1: Hardware Queue (=HW CQ, 2D queue, 3D queue) empty
+   bit 29 = 1: 2D engine is idle
+   bit 28 = 1: 3D engine is idle
+   bit 27 = 1: HW command queue empty
+   bit 26 = 1: 2D queue empty
+   bit 25 = 1: 3D queue empty
+   bit 24 = 1: SW command queue empty
+   bits 23:16: 2D counter 3
+   bits 15:8:  2D counter 2
+   bits 7:0:   2D counter 1
+
+   Where is the command queue length (current amount of commands the queue
+   can accept) on the 310/325 series? (The current implementation is taken
+   from 300 series and certainly wrong...)
+*/
+
+/* TW: FIXME: xgiCmdQueLen is... where....? */
+#define XGI310Idle \
+  { \
+  while( (MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+  while( (MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+  xgiCmdQueLen=MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS); \
+  }
+
+#define XGI310SetupSRCBase(base) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_ADDR, base);\
+      xgiCmdQueLen--;
+
+#define XGI310SetupSRCPitch(pitch) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT16(xgi_video_info.mmio_vbase, SRC_PITCH, pitch);\
+      xgiCmdQueLen--;
+
+#define XGI310SetupSRCXY(x,y) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_Y, (x)<<16 | (y) );\
+      xgiCmdQueLen--;
+
+#define XGI310SetupDSTBase(base) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, DST_ADDR, base);\
+      xgiCmdQueLen--;
+
+#define XGI310SetupDSTXY(x,y) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, DST_Y, (x)<<16 | (y) );\
+      xgiCmdQueLen--;
+
+#define XGI310SetupDSTRect(x,y) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
+      xgiCmdQueLen--;
+
+#define XGI310SetupDSTColorDepth(bpp) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT16(xgi_video_info.mmio_vbase, AGP_BASE, bpp);\
+      xgiCmdQueLen--;
+
+#define XGI310SetupRect(w,h) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
+      xgiCmdQueLen--;
+
+#define XGI310SetupPATFG(color) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, PAT_FGCOLOR, color);\
+      xgiCmdQueLen--;
+
+#define XGI310SetupPATBG(color) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, PAT_BGCOLOR, color);\
+      xgiCmdQueLen--;
+
+#define XGI310SetupSRCFG(color) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_FGCOLOR, color);\
+      xgiCmdQueLen--;
+
+#define XGI310SetupSRCBG(color) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_BGCOLOR, color);\
+      xgiCmdQueLen--;
+
+#define XGI310SetupSRCTrans(color) \
+      if (xgiCmdQueLen <= 1)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_SRC_KEY_LOW, color);\
+      xgiCmdQueLen -= 2;
+
+#define XGI310SetupDSTTrans(color) \
+      if (xgiCmdQueLen <= 1)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_DST_KEY_HIGH, color); \
+      MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_DST_KEY_LOW, color); \
+      xgiCmdQueLen -= 2;
+
+#define XGI310SetupMONOPAT(p0,p1) \
+      if (xgiCmdQueLen <= 1)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, MONO_MASK, p0);\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, MONO_MASK+4, p1);\
+      xgiCmdQueLen -= 2;
+
+#define XGI310SetupClipLT(left,top) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
+      xgiCmdQueLen--;
+
+#define XGI310SetupClipRB(right,bottom) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
+      xgiCmdQueLen--;
+
+#define XGI310SetupROP(rop) \
+      xgi_video_info.CommandReg = (rop) << 8;
+
+#define XGI310SetupCMDFlag(flags) \
+      xgi_video_info.CommandReg |= (flags);
+
+#define XGI310DoCMD \
+      if (xgiCmdQueLen <= 1)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, COMMAND_READY, xgi_video_info.CommandReg); \
+      MMIO_OUT32(xgi_video_info.mmio_vbase, FIRE_TRIGGER, 0); \
+      xgiCmdQueLen -= 2;
+
+#define XGI310SetupX0Y0(x,y) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_X0, (y)<<16 | (x) );\
+      xgiCmdQueLen--;
+
+#define XGI310SetupX1Y1(x,y) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_X1, (y)<<16 | (x) );\
+      xgiCmdQueLen--;
+
+#define XGI310SetupLineCount(c) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT16(xgi_video_info.mmio_vbase, LINE_COUNT, c);\
+      xgiCmdQueLen--;
+
+#define XGI310SetupStylePeriod(p) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT16(xgi_video_info.mmio_vbase, LINE_STYLE_PERIOD, p);\
+      xgiCmdQueLen--;
+
+#define XGI310SetupStyleLow(ls) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_STYLE_0, ls);\
+      xgiCmdQueLen--;
+
+#define XGI310SetupStyleHigh(ls) \
+      if (xgiCmdQueLen <= 0)  XGI310Idle;\
+      MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_STYLE_1, ls);\
+      xgiCmdQueLen--;
+
+int  XGIfb_initaccel(void);
+void XGIfb_syncaccel(void);
+
+extern struct video_info xgi_video_info;
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
+void fbcon_XGI_bmove(struct display *p, int srcy, int srcx, int dsty,
+                     int dstx, int height, int width);
+void fbcon_XGI_revc(struct display *p, int srcy, int srcx);
+void fbcon_XGI_clear8(struct vc_data *conp, struct display *p, int srcy,
+                      int srcx, int height, int width);
+void fbcon_XGI_clear16(struct vc_data *conp, struct display *p, int srcy,
+                       int srcx, int height, int width);
+void fbcon_XGI_clear32(struct vc_data *conp, struct display *p, int srcy,
+                       int srcx, int height, int width);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
+extern int XGIfb_accel;
+void fbcon_XGI_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
+void fbcon_XGI_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+#endif
+
+#endif
diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
new file mode 100644 (file)
index 0000000..4f4171e
--- /dev/null
@@ -0,0 +1,1023 @@
+#ifndef _XGIFB_MAIN
+#define _XGIFB_MAIN
+
+
+/* ------------------- Constant Definitions ------------------------- */
+
+
+#include "XGIfb.h"
+#include "vb_struct.h"
+#include "vb_def.h"
+
+//#define LINUXBIOS   /* turn this on when compiling for LINUXBIOS */
+#define AGPOFF     /* default is turn off AGP */
+
+#define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
+
+#define VER_MAJOR                 0
+#define VER_MINOR                 8
+#define VER_LEVEL                 1
+
+#define DRIVER_DESC  "XGI Volari Frame Buffer Module Version 0.8.1"
+
+#ifndef PCI_VENDOR_ID_XG
+#define PCI_VENDOR_ID_XG          0x18CA
+#endif
+
+#ifndef PCI_DEVICE_ID_XG_40
+#define PCI_DEVICE_ID_XG_40      0x040
+#endif
+#ifndef PCI_DEVICE_ID_XG_41
+#define PCI_DEVICE_ID_XG_41      0x041
+#endif
+#ifndef PCI_DEVICE_ID_XG_42
+#define PCI_DEVICE_ID_XG_42      0x042
+#endif
+#ifndef PCI_DEVICE_ID_XG_20
+#define PCI_DEVICE_ID_XG_20      0x020
+#endif
+#ifndef PCI_DEVICE_ID_XG_27
+#define PCI_DEVICE_ID_XG_27      0x027
+#endif
+
+
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+#define XGI_IOTYPE1 void __iomem
+#define XGI_IOTYPE2 __iomem
+#define XGIINITSTATIC static
+#else
+#define XGI_IOTYPE1 unsigned char
+#define XGI_IOTYPE2
+#define XGIINITSTATIC
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static struct pci_device_id __devinitdata xgifb_pci_table[] = {
+
+       { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_27, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+       { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_40, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+       { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
+#endif
+/* To be included in fb.h */
+#ifndef FB_ACCEL_XGI_GLAMOUR_2
+#define FB_ACCEL_XGI_GLAMOUR_2  40     /* XGI 315, 650, 740            */
+#endif
+#ifndef FB_ACCEL_XGI_XABRE
+#define FB_ACCEL_XGI_XABRE      41     /* XGI 330 ("Xabre")            */
+#endif
+
+#define MAX_ROM_SCAN              0x10000
+
+#define HW_CURSOR_CAP             0x80
+#define TURBO_QUEUE_CAP           0x40
+#define AGP_CMD_QUEUE_CAP         0x20
+#define VM_CMD_QUEUE_CAP          0x10
+#define MMIO_CMD_QUEUE_CAP        0x08
+
+
+
+/* For 315 series */
+
+#define COMMAND_QUEUE_AREA_SIZE   0x80000 /* 512K */
+#define COMMAND_QUEUE_THRESHOLD   0x1F
+
+
+/* TW */
+#define HW_CURSOR_AREA_SIZE_315   0x4000  /* 16K */
+#define HW_CURSOR_AREA_SIZE_300   0x1000  /* 4K */
+
+#define OH_ALLOC_SIZE             4000
+#define SENTINEL                  0x7fffffff
+
+#define SEQ_ADR                   0x14
+#define SEQ_DATA                  0x15
+#define DAC_ADR                   0x18
+#define DAC_DATA                  0x19
+#define CRTC_ADR                  0x24
+#define CRTC_DATA                 0x25
+#define DAC2_ADR                  (0x16-0x30)
+#define DAC2_DATA                 (0x17-0x30)
+#define VB_PART1_ADR              (0x04-0x30)
+#define VB_PART1_DATA             (0x05-0x30)
+#define VB_PART2_ADR              (0x10-0x30)
+#define VB_PART2_DATA             (0x11-0x30)
+#define VB_PART3_ADR              (0x12-0x30)
+#define VB_PART3_DATA             (0x13-0x30)
+#define VB_PART4_ADR              (0x14-0x30)
+#define VB_PART4_DATA             (0x15-0x30)
+
+#define XGISR                    XGI_Pr.P3c4
+#define XGICR                     XGI_Pr.P3d4
+#define XGIDACA                   XGI_Pr.P3c8
+#define XGIDACD                   XGI_Pr.P3c9
+#define XGIPART1                  XGI_Pr.Part1Port
+#define XGIPART2                  XGI_Pr.Part2Port
+#define XGIPART3                  XGI_Pr.Part3Port
+#define XGIPART4                  XGI_Pr.Part4Port
+#define XGIPART5                  XGI_Pr.Part5Port
+#define XGIDAC2A                  XGIPART5
+#define XGIDAC2D                  (XGIPART5 + 1)
+#define XGIMISCR                  (XGI_Pr.RelIO + 0x1c)
+#define XGIINPSTAT               (XGI_Pr.RelIO + 0x2a)
+
+#define IND_XGI_PASSWORD          0x05  /* SRs */
+#define IND_XGI_COLOR_MODE        0x06
+#define IND_XGI_RAMDAC_CONTROL    0x07
+#define IND_XGI_DRAM_SIZE         0x14
+#define IND_XGI_SCRATCH_REG_16    0x16
+#define IND_XGI_SCRATCH_REG_17    0x17
+#define IND_XGI_SCRATCH_REG_1A    0x1A
+#define IND_XGI_MODULE_ENABLE     0x1E
+#define IND_XGI_PCI_ADDRESS_SET   0x20
+#define IND_XGI_TURBOQUEUE_ADR    0x26
+#define IND_XGI_TURBOQUEUE_SET    0x27
+#define IND_XGI_POWER_ON_TRAP     0x38
+#define IND_XGI_POWER_ON_TRAP2    0x39
+#define IND_XGI_CMDQUEUE_SET      0x26
+#define IND_XGI_CMDQUEUE_THRESHOLD  0x27
+
+#define IND_XGI_SCRATCH_REG_CR30  0x30  /* CRs */
+#define IND_XGI_SCRATCH_REG_CR31  0x31
+#define IND_XGI_SCRATCH_REG_CR32  0x32
+#define IND_XGI_SCRATCH_REG_CR33  0x33
+#define IND_XGI_LCD_PANEL         0x36
+#define IND_XGI_SCRATCH_REG_CR37  0x37
+#define IND_XGI_AGP_IO_PAD        0x48
+
+#define IND_BRI_DRAM_STATUS       0x63 /* PCI config memory size offset */
+
+#define MMIO_QUEUE_PHYBASE        0x85C0
+#define MMIO_QUEUE_WRITEPORT      0x85C4
+#define MMIO_QUEUE_READPORT       0x85C8
+
+#define IND_XGI_CRT2_WRITE_ENABLE_300 0x24
+#define IND_XGI_CRT2_WRITE_ENABLE_315 0x2F
+
+#define XGI_PASSWORD              0x86  /* SR05 */
+#define XGI_INTERLACED_MODE       0x20  /* SR06 */
+#define XGI_8BPP_COLOR_MODE       0x0
+#define XGI_15BPP_COLOR_MODE      0x1
+#define XGI_16BPP_COLOR_MODE      0x2
+#define XGI_32BPP_COLOR_MODE      0x4
+
+#define XGI_DRAM_SIZE_MASK     0xF0  /*SR14 */
+#define XGI_DRAM_SIZE_1MB      0x00
+#define XGI_DRAM_SIZE_2MB      0x01
+#define XGI_DRAM_SIZE_4MB      0x02
+#define XGI_DRAM_SIZE_8MB      0x03
+#define XGI_DRAM_SIZE_16MB     0x04
+#define XGI_DRAM_SIZE_32MB     0x05
+#define XGI_DRAM_SIZE_64MB     0x06
+#define XGI_DRAM_SIZE_128MB    0x07
+#define XGI_DRAM_SIZE_256MB    0x08
+#define XGI_DATA_BUS_MASK      0x02
+#define XGI_DATA_BUS_64        0x00
+#define XGI_DATA_BUS_128       0x01
+#define XGI_DUAL_CHANNEL_MASK  0x0C
+#define XGI_SINGLE_CHANNEL_1_RANK      0x0
+#define XGI_SINGLE_CHANNEL_2_RANK      0x1
+#define XGI_ASYM_DDR                   0x02
+#define XGI_DUAL_CHANNEL_1_RANK        0x3
+
+#define XGI550_DRAM_SIZE_MASK     0x3F  /* 550/650/740 SR14 */
+#define XGI550_DRAM_SIZE_4MB      0x00
+#define XGI550_DRAM_SIZE_8MB      0x01
+#define XGI550_DRAM_SIZE_16MB     0x03
+#define XGI550_DRAM_SIZE_24MB     0x05
+#define XGI550_DRAM_SIZE_32MB     0x07
+#define XGI550_DRAM_SIZE_64MB     0x0F
+#define XGI550_DRAM_SIZE_96MB     0x17
+#define XGI550_DRAM_SIZE_128MB    0x1F
+#define XGI550_DRAM_SIZE_256MB    0x3F
+
+#define XGI_SCRATCH_REG_1A_MASK   0x10
+
+#define XGI_ENABLE_2D             0x40  /* SR1E */
+
+#define XGI_MEM_MAP_IO_ENABLE     0x01  /* SR20 */
+#define XGI_PCI_ADDR_ENABLE       0x80
+
+#define XGI_AGP_CMDQUEUE_ENABLE   0x80  /* 315/650/740 SR26 */
+#define XGI_VRAM_CMDQUEUE_ENABLE  0x40
+#define XGI_MMIO_CMD_ENABLE       0x20
+#define XGI_CMD_QUEUE_SIZE_512k   0x00
+#define XGI_CMD_QUEUE_SIZE_1M     0x04
+#define XGI_CMD_QUEUE_SIZE_2M     0x08
+#define XGI_CMD_QUEUE_SIZE_4M     0x0C
+#define XGI_CMD_QUEUE_RESET       0x01
+#define XGI_CMD_AUTO_CORR        0x02
+
+#define XGI_SIMULTANEOUS_VIEW_ENABLE  0x01  /* CR30 */
+#define XGI_MODE_SELECT_CRT2      0x02
+#define XGI_VB_OUTPUT_COMPOSITE   0x04
+#define XGI_VB_OUTPUT_SVIDEO      0x08
+#define XGI_VB_OUTPUT_SCART       0x10
+#define XGI_VB_OUTPUT_LCD         0x20
+#define XGI_VB_OUTPUT_CRT2        0x40
+#define XGI_VB_OUTPUT_HIVISION    0x80
+
+#define XGI_VB_OUTPUT_DISABLE     0x20  /* CR31 */
+#define XGI_DRIVER_MODE           0x40
+
+#define XGI_VB_COMPOSITE          0x01  /* CR32 */
+#define XGI_VB_SVIDEO             0x02
+#define XGI_VB_SCART              0x04
+#define XGI_VB_LCD                0x08
+#define XGI_VB_CRT2               0x10
+#define XGI_CRT1                  0x20
+#define XGI_VB_HIVISION           0x40
+#define XGI_VB_YPBPR                0x80
+#define XGI_VB_TV                 (XGI_VB_COMPOSITE | XGI_VB_SVIDEO | \
+                                   XGI_VB_SCART | XGI_VB_HIVISION|XGI_VB_YPBPR)
+
+#define XGI_EXTERNAL_CHIP_MASK            0x0E  /* CR37 */
+#define XGI_EXTERNAL_CHIP_XGI301           0x01  /* in CR37 << 1 ! */
+#define XGI_EXTERNAL_CHIP_LVDS             0x02  /* in CR37 << 1 ! */
+#define XGI_EXTERNAL_CHIP_TRUMPION         0x03  /* in CR37 << 1 ! */
+#define XGI_EXTERNAL_CHIP_LVDS_CHRONTEL    0x04  /* in CR37 << 1 ! */
+#define XGI_EXTERNAL_CHIP_CHRONTEL         0x05  /* in CR37 << 1 ! */
+#define XGI310_EXTERNAL_CHIP_LVDS          0x02  /* in CR37 << 1 ! */
+#define XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03  /* in CR37 << 1 ! */
+
+#define XGI_AGP_2X                0x20  /* CR48 */
+
+#define BRI_DRAM_SIZE_MASK        0x70  /* PCI bridge config data */
+#define BRI_DRAM_SIZE_2MB         0x00
+#define BRI_DRAM_SIZE_4MB         0x01
+#define BRI_DRAM_SIZE_8MB         0x02
+#define BRI_DRAM_SIZE_16MB        0x03
+#define BRI_DRAM_SIZE_32MB        0x04
+#define BRI_DRAM_SIZE_64MB        0x05
+
+#define HW_DEVICE_EXTENSION      XGI_HW_DEVICE_INFO
+#define PHW_DEVICE_EXTENSION      PXGI_HW_DEVICE_INFO
+
+#define SR_BUFFER_SIZE            5
+#define CR_BUFFER_SIZE            5
+
+/* Useful macros */
+#define inXGIREG(base)          inb(base)
+#define outXGIREG(base,val)     outb(val,base)
+#define orXGIREG(base,val)      do { \
+                                  unsigned char __Temp = inb(base); \
+                                  outXGIREG(base, __Temp | (val)); \
+                                } while (0)
+#define andXGIREG(base,val)     do { \
+                                  unsigned char __Temp = inb(base); \
+                                  outXGIREG(base, __Temp & (val)); \
+                                } while (0)
+#define inXGIIDXREG(base,idx,var)   do { \
+                                      outb(idx,base); var=inb((base)+1); \
+                                    } while (0)
+#define outXGIIDXREG(base,idx,val)  do { \
+                                      outb(idx,base); outb((val),(base)+1); \
+                                    } while (0)
+#define orXGIIDXREG(base,idx,val)   do { \
+                                      unsigned char __Temp; \
+                                      outb(idx,base);   \
+                                      __Temp = inb((base)+1)|(val); \
+                                      outXGIIDXREG(base,idx,__Temp); \
+                                    } while (0)
+#define andXGIIDXREG(base,idx,and)  do { \
+                                      unsigned char __Temp; \
+                                      outb(idx,base);   \
+                                      __Temp = inb((base)+1)&(and); \
+                                      outXGIIDXREG(base,idx,__Temp); \
+                                    } while (0)
+#define setXGIIDXREG(base,idx,and,or)   do { \
+                                          unsigned char __Temp; \
+                                          outb(idx,base);   \
+                                          __Temp = (inb((base)+1)&(and))|(or); \
+                                          outXGIIDXREG(base,idx,__Temp); \
+                                        } while (0)
+
+/* ------------------- Global Variables ----------------------------- */
+
+/* Fbcon variables */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static struct fb_info* fb_info;
+#else
+static struct fb_info XGI_fb_info;
+#endif
+
+
+static int    video_type = FB_TYPE_PACKED_PIXELS;
+
+static struct fb_var_screeninfo default_var = {
+       .xres           = 0,
+       .yres           = 0,
+       .xres_virtual   = 0,
+       .yres_virtual   = 0,
+       .xoffset        = 0,
+       .yoffset        = 0,
+       .bits_per_pixel = 0,
+       .grayscale      = 0,
+       .red            = {0, 8, 0},
+       .green          = {0, 8, 0},
+       .blue           = {0, 8, 0},
+       .transp         = {0, 0, 0},
+       .nonstd         = 0,
+       .activate       = FB_ACTIVATE_NOW,
+       .height         = -1,
+       .width          = -1,
+       .accel_flags    = 0,
+       .pixclock       = 0,
+       .left_margin    = 0,
+       .right_margin   = 0,
+       .upper_margin   = 0,
+       .lower_margin   = 0,
+       .hsync_len      = 0,
+       .vsync_len      = 0,
+       .sync           = 0,
+       .vmode          = FB_VMODE_NONINTERLACED,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+       .reserved       = {0, 0, 0, 0, 0, 0}
+#endif
+};
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static struct fb_fix_screeninfo XGIfb_fix = {
+       .id             = "XGI",
+       .type           = FB_TYPE_PACKED_PIXELS,
+       .xpanstep       = 1,
+       .ypanstep       = 1,
+};
+static char myid[20];
+static u32 pseudo_palette[17];
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static struct display XGI_disp;
+
+static struct display_switch XGIfb_sw;
+
+static struct {
+       u16 blue, green, red, pad;
+} XGI_palette[256];
+
+static union {
+#ifdef FBCON_HAS_CFB16
+       u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+       u32 cfb32[16];
+#endif
+} XGI_fbcon_cmap;
+
+static int XGIfb_inverse = 0;
+#endif
+
+/* display status */
+static int XGIfb_off = 0;
+static int XGIfb_crt1off = 0;
+static int XGIfb_forcecrt1 = -1;
+static int XGIvga_enabled = 0;
+static int XGIfb_userom = 0;
+//static int XGIfb_useoem = -1;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static int currcon = 0;
+#endif
+
+/* global flags */
+static int XGIfb_registered;
+static int XGIfb_tvmode = 0;
+static int XGIfb_mem = 0;
+static int XGIfb_pdc = 0;
+static int enable_dstn = 0;
+static int XGIfb_ypan = -1;
+
+
+int       XGIfb_accel = 0;
+
+
+static int XGIfb_hwcursor_size = 0;
+static int XGIfb_CRT2_write_enable = 0;
+
+int XGIfb_crt2type  = -1;      /* TW: CRT2 type (for overriding autodetection) */
+int XGIfb_tvplug    = -1;      /* PR: Tv plug type (for overriding autodetection) */
+
+int XGIfb_queuemode = -1;      /* TW: Use MMIO queue mode by default (310/325 series only) */
+
+unsigned char XGIfb_detectedpdc = 0;
+
+unsigned char XGIfb_detectedlcda = 0xff;
+
+
+
+
+/* TW: For ioctl XGIFB_GET_INFO */
+/* XGIfb_info XGIfbinfo; */
+
+/* TW: Hardware extension; contains data on hardware */
+HW_DEVICE_EXTENSION XGIhw_ext;
+
+/* TW: XGI private structure */
+VB_DEVICE_INFO  XGI_Pr;
+
+/* card parameters */
+static unsigned long XGIfb_mmio_size = 0;
+static u8            XGIfb_caps = 0;
+
+typedef enum _XGI_CMDTYPE {
+       MMIO_CMD = 0,
+       AGP_CMD_QUEUE,
+       VM_CMD_QUEUE,
+} XGI_CMDTYPE;
+
+#define MD_XGI300 1
+#define MD_XGI315 2
+
+/* mode table */
+/* NOT const - will be patched for 1280x960 mode number chaos reasons */
+struct _XGIbios_mode {
+       char name[15];
+       u8 mode_no;
+       u16 vesa_mode_no_1;  /* "XGI defined" VESA mode number */
+       u16 vesa_mode_no_2;  /* Real VESA mode numbers */
+       u16 xres;
+       u16 yres;
+       u16 bpp;
+       u16 rate_idx;
+       u16 cols;
+       u16 rows;
+       u8  chipset;
+} XGIbios_mode[] = {
+#define MODE_INDEX_NONE           0  /* TW: index for mode=none */
+       {"none",         0xFF, 0x0000, 0x0000,    0,    0,  0, 0,   0,  0, MD_XGI300|MD_XGI315},  /* TW: for mode "none" */
+       {"320x240x16",   0x56, 0x0000, 0x0000,  320,  240, 16, 1,  40, 15,           MD_XGI315},
+       {"320x480x8",    0x5A, 0x0000, 0x0000,  320,  480,  8, 1,  40, 30,           MD_XGI315},  /* TW: FSTN */
+       {"320x480x16",   0x5B, 0x0000, 0x0000,  320,  480, 16, 1,  40, 30,           MD_XGI315},  /* TW: FSTN */
+       {"640x480x8",    0x2E, 0x0101, 0x0101,  640,  480,  8, 1,  80, 30, MD_XGI300|MD_XGI315},
+       {"640x480x16",   0x44, 0x0111, 0x0111,  640,  480, 16, 1,  80, 30, MD_XGI300|MD_XGI315},
+       {"640x480x24",   0x62, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_XGI300|MD_XGI315},  /* TW: That's for people who mix up color- and fb depth */
+       {"640x480x32",   0x62, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_XGI300|MD_XGI315},
+       {"720x480x8",    0x31, 0x0000, 0x0000,  720,  480,  8, 1,  90, 30, MD_XGI300|MD_XGI315},
+       {"720x480x16",   0x33, 0x0000, 0x0000,  720,  480, 16, 1,  90, 30, MD_XGI300|MD_XGI315},
+       {"720x480x24",   0x35, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_XGI300|MD_XGI315},
+       {"720x480x32",   0x35, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_XGI300|MD_XGI315},
+       {"720x576x8",    0x32, 0x0000, 0x0000,  720,  576,  8, 1,  90, 36, MD_XGI300|MD_XGI315},
+       {"720x576x16",   0x34, 0x0000, 0x0000,  720,  576, 16, 1,  90, 36, MD_XGI300|MD_XGI315},
+       {"720x576x24",   0x36, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_XGI300|MD_XGI315},
+       {"720x576x32",   0x36, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_XGI300|MD_XGI315},
+       {"800x480x8",    0x70, 0x0000, 0x0000,  800,  480,  8, 1, 100, 30, MD_XGI300|MD_XGI315},
+       {"800x480x16",   0x7a, 0x0000, 0x0000,  800,  480, 16, 1, 100, 30, MD_XGI300|MD_XGI315},
+       {"800x480x24",   0x76, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_XGI300|MD_XGI315},
+       {"800x480x32",   0x76, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_XGI300|MD_XGI315},
+#define DEFAULT_MODE              21 /* TW: index for 800x600x8 */
+#define DEFAULT_LCDMODE           21 /* TW: index for 800x600x8 */
+#define DEFAULT_TVMODE            21 /* TW: index for 800x600x8 */
+       {"800x600x8",    0x30, 0x0103, 0x0103,  800,  600,  8, 1, 100, 37, MD_XGI300|MD_XGI315},
+       {"800x600x16",   0x47, 0x0114, 0x0114,  800,  600, 16, 1, 100, 37, MD_XGI300|MD_XGI315},
+       {"800x600x24",   0x63, 0x013b, 0x0115,  800,  600, 32, 1, 100, 37, MD_XGI300|MD_XGI315},
+       {"800x600x32",   0x63, 0x013b, 0x0115,  800,  600, 32, 1, 100, 37, MD_XGI300|MD_XGI315},
+       {"1024x576x8",   0x71, 0x0000, 0x0000, 1024,  576,  8, 1, 128, 36, MD_XGI300|MD_XGI315},
+       {"1024x576x16",  0x74, 0x0000, 0x0000, 1024,  576, 16, 1, 128, 36, MD_XGI300|MD_XGI315},
+       {"1024x576x24",  0x77, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_XGI300|MD_XGI315},
+       {"1024x576x32",  0x77, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_XGI300|MD_XGI315},
+       {"1024x600x8",   0x20, 0x0000, 0x0000, 1024,  600,  8, 1, 128, 37, MD_XGI300          },  /* TW: 300 series only */
+       {"1024x600x16",  0x21, 0x0000, 0x0000, 1024,  600, 16, 1, 128, 37, MD_XGI300          },
+       {"1024x600x24",  0x22, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_XGI300          },
+       {"1024x600x32",  0x22, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_XGI300          },
+       {"1024x768x8",   0x38, 0x0105, 0x0105, 1024,  768,  8, 1, 128, 48, MD_XGI300|MD_XGI315},
+       {"1024x768x16",  0x4A, 0x0117, 0x0117, 1024,  768, 16, 1, 128, 48, MD_XGI300|MD_XGI315},
+       {"1024x768x24",  0x64, 0x013c, 0x0118, 1024,  768, 32, 1, 128, 48, MD_XGI300|MD_XGI315},
+       {"1024x768x32",  0x64, 0x013c, 0x0118, 1024,  768, 32, 1, 128, 48, MD_XGI300|MD_XGI315},
+       {"1152x768x8",   0x23, 0x0000, 0x0000, 1152,  768,  8, 1, 144, 48, MD_XGI300          },  /* TW: 300 series only */
+       {"1152x768x16",  0x24, 0x0000, 0x0000, 1152,  768, 16, 1, 144, 48, MD_XGI300          },
+       {"1152x768x24",  0x25, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_XGI300          },
+       {"1152x768x32",  0x25, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_XGI300          },
+       {"1280x720x8",   0x79, 0x0000, 0x0000, 1280,  720,  8, 1, 160, 45, MD_XGI300|MD_XGI315},
+       {"1280x720x16",  0x75, 0x0000, 0x0000, 1280,  720, 16, 1, 160, 45, MD_XGI300|MD_XGI315},
+       {"1280x720x24",  0x78, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_XGI300|MD_XGI315},
+       {"1280x720x32",  0x78, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_XGI300|MD_XGI315},
+       {"1280x768x8",   0x23, 0x0000, 0x0000, 1280,  768,  8, 1, 160, 48,           MD_XGI315},  /* TW: 310/325 series only */
+       {"1280x768x16",  0x24, 0x0000, 0x0000, 1280,  768, 16, 1, 160, 48,           MD_XGI315},
+       {"1280x768x24",  0x25, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48,           MD_XGI315},
+       {"1280x768x32",  0x25, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48,           MD_XGI315},
+#define MODEINDEX_1280x960 48
+       {"1280x960x8",   0x7C, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_XGI300|MD_XGI315},  /* TW: Modenumbers being patched */
+       {"1280x960x16",  0x7D, 0x0000, 0x0000, 1280,  960, 16, 1, 160, 60, MD_XGI300|MD_XGI315},
+       {"1280x960x24",  0x7E, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_XGI300|MD_XGI315},
+       {"1280x960x32",  0x7E, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_XGI300|MD_XGI315},
+       {"1280x1024x8",  0x3A, 0x0107, 0x0107, 1280, 1024,  8, 1, 160, 64, MD_XGI300|MD_XGI315},
+       {"1280x1024x16", 0x4D, 0x011a, 0x011a, 1280, 1024, 16, 1, 160, 64, MD_XGI300|MD_XGI315},
+       {"1280x1024x24", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 1, 160, 64, MD_XGI300|MD_XGI315},
+       {"1280x1024x32", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 1, 160, 64, MD_XGI300|MD_XGI315},
+       {"1400x1050x8",  0x26, 0x0000, 0x0000, 1400, 1050,  8, 1, 175, 65,           MD_XGI315},  /* TW: 310/325 series only */
+       {"1400x1050x16", 0x27, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65,           MD_XGI315},
+       {"1400x1050x24", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_XGI315},
+       {"1400x1050x32", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_XGI315},
+       {"1600x1200x8",  0x3C, 0x0130, 0x011c, 1600, 1200,  8, 1, 200, 75, MD_XGI300|MD_XGI315},
+       {"1600x1200x16", 0x3D, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_XGI300|MD_XGI315},
+       {"1600x1200x24", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_XGI300|MD_XGI315},
+       {"1600x1200x32", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_XGI300|MD_XGI315},
+       {"1920x1440x8",  0x68, 0x013f, 0x0000, 1920, 1440,  8, 1, 240, 75, MD_XGI300|MD_XGI315},
+       {"1920x1440x16", 0x69, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_XGI300|MD_XGI315},
+       {"1920x1440x24", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_XGI300|MD_XGI315},
+       {"1920x1440x32", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_XGI300|MD_XGI315},
+       {"2048x1536x8",  0x6c, 0x0000, 0x0000, 2048, 1536,  8, 1, 256, 96,           MD_XGI315},  /* TW: 310/325 series only */
+       {"2048x1536x16", 0x6d, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96,           MD_XGI315},
+       {"2048x1536x24", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_XGI315},
+       {"2048x1536x32", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_XGI315},
+       {"\0", 0x00, 0, 0, 0, 0, 0, 0, 0}
+};
+
+/* mode-related variables */
+#ifdef MODULE
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static int xgifb_mode_idx = 1;
+#else
+static int XGIfb_mode_idx = MODE_INDEX_NONE;  /* Don't use a mode by default if we are a module */
+#endif
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static int xgifb_mode_idx = -1;               /* Use a default mode if we are inside the kernel */
+#else
+static int XGIfb_mode_idx = -1;
+#endif
+#endif
+u8  XGIfb_mode_no  = 0;
+u8  XGIfb_rate_idx = 0;
+
+/* TW: CR36 evaluation */
+const USHORT XGI300paneltype[] =
+    { LCD_UNKNOWN,   LCD_800x600,  LCD_1024x768,  LCD_1280x1024,
+      LCD_1280x960,  LCD_640x480,  LCD_1024x600,  LCD_1152x768,
+       LCD_1024x768, LCD_1024x768,  LCD_1024x768,
+      LCD_1024x768,  LCD_1024x768, LCD_1024x768,  LCD_1024x768 };
+
+const USHORT XGI310paneltype[] =
+    { LCD_UNKNOWN,   LCD_800x600,  LCD_1024x768,  LCD_1280x1024,
+      LCD_640x480,   LCD_1024x600, LCD_1152x864,  LCD_1280x960,
+      LCD_1152x768,  LCD_1400x1050,LCD_1280x768,  LCD_1600x1200,
+      LCD_1024x768, LCD_1024x768,  LCD_1024x768 };
+
+static const struct _XGI_crt2type {
+       char name[10];
+       int type_no;
+       int tvplug_no;
+} XGI_crt2type[] = {
+       {"NONE",        0,              -1},
+       {"LCD",         DISPTYPE_LCD,   -1},
+       {"TV",          DISPTYPE_TV,    -1},
+       {"VGA",         DISPTYPE_CRT2,  -1},
+       {"SVIDEO",      DISPTYPE_TV,    TVPLUG_SVIDEO},
+       {"COMPOSITE",   DISPTYPE_TV,    TVPLUG_COMPOSITE},
+       {"SCART",       DISPTYPE_TV,    TVPLUG_SCART},
+       {"none",        0,              -1},
+       {"lcd",         DISPTYPE_LCD,   -1},
+       {"tv",          DISPTYPE_TV,    -1},
+       {"vga",         DISPTYPE_CRT2,  -1},
+       {"svideo",      DISPTYPE_TV,    TVPLUG_SVIDEO},
+       {"composite",   DISPTYPE_TV,    TVPLUG_COMPOSITE},
+       {"scart",       DISPTYPE_TV,    TVPLUG_SCART},
+       {"\0",          -1,             -1}
+};
+
+/* Queue mode selection for 310 series */
+static const struct _XGI_queuemode {
+       char name[6];
+       int type_no;
+} XGI_queuemode[] = {
+       {"AGP",         AGP_CMD_QUEUE},
+       {"VRAM",        VM_CMD_QUEUE},
+       {"MMIO",        MMIO_CMD},
+       {"agp",         AGP_CMD_QUEUE},
+       {"vram",        VM_CMD_QUEUE},
+       {"mmio",        MMIO_CMD},
+       {"\0",          -1}
+};
+
+/* TV standard */
+static const struct _XGI_tvtype {
+       char name[6];
+       int type_no;
+} XGI_tvtype[] = {
+       {"PAL",         1},
+       {"NTSC",        2},
+       {"pal",         1},
+       {"ntsc",        2},
+       {"\0",          -1}
+};
+
+static const struct _XGI_vrate {
+       u16 idx;
+       u16 xres;
+       u16 yres;
+       u16 refresh;
+} XGIfb_vrate[] = {
+       {1,  640,  480, 60}, {2,  640,  480,  72}, {3, 640,   480,  75}, {4,  640, 480,  85},
+       {5,  640,  480,100}, {6,  640,  480, 120}, {7, 640,   480, 160}, {8,  640, 480, 200},
+       {1,  720,  480, 60},
+       {1,  720,  576, 58},
+       {1,  800,  480, 60}, {2,  800,  480,  75}, {3, 800,   480,  85},
+        {1,  800,  600,  60}, {2, 800,   600,  72}, {3,  800, 600,  75},
+       {4,  800,  600, 85}, {5,  800,  600, 100}, {6, 800,   600, 120}, {7,  800, 600, 160},
+       {1, 1024,  768,  60}, {2, 1024,  768,  70}, {3, 1024, 768,  75},
+       {4, 1024,  768, 85}, {5, 1024,  768, 100}, {6, 1024,  768, 120},
+       {1, 1024,  576, 60}, {2, 1024,  576,  75}, {3, 1024,  576,  85},
+       {1, 1024,  600, 60},
+       {1, 1152,  768, 60},
+       {1, 1280,  720, 60}, {2, 1280,  720,  75}, {3, 1280,  720,  85},
+       {1, 1280,  768, 60},
+        {1, 1280, 1024,  60}, {2, 1280, 1024,  75}, {3, 1280, 1024,  85},
+       {1, 1280,  960, 70},
+       {1, 1400, 1050, 60},
+       {1, 1600, 1200, 60}, {2, 1600, 1200,  65}, {3, 1600, 1200,  70}, {4, 1600, 1200,  75},
+       {5, 1600, 1200, 85}, {6, 1600, 1200, 100}, {7, 1600, 1200, 120},
+       {1, 1920, 1440, 60}, {2, 1920, 1440,  65}, {3, 1920, 1440,  70}, {4, 1920, 1440,  75},
+       {5, 1920, 1440, 85}, {6, 1920, 1440, 100},
+       {1, 2048, 1536, 60}, {2, 2048, 1536,  65}, {3, 2048, 1536,  70}, {4, 2048, 1536,  75},
+       {5, 2048, 1536, 85},
+       {0, 0, 0, 0}
+};
+
+static const struct _chswtable {
+    int subsysVendor;
+    int subsysCard;
+    char *vendorName;
+    char *cardName;
+} mychswtable[] = {
+        { 0x1631, 0x1002, "Mitachi", "0x1002" },
+       { 0,      0,      ""       , ""       }
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+/* Offscreen layout */
+typedef struct _XGI_GLYINFO {
+       unsigned char ch;
+       int fontwidth;
+       int fontheight;
+       u8 gmask[72];
+       int ngmask;
+} XGI_GLYINFO;
+#endif
+
+typedef struct _XGI_OH {
+       struct _XGI_OH *poh_next;
+       struct _XGI_OH *poh_prev;
+       unsigned long offset;
+       unsigned long size;
+} XGI_OH;
+
+typedef struct _XGI_OHALLOC {
+       struct _XGI_OHALLOC *poha_next;
+       XGI_OH aoh[1];
+} XGI_OHALLOC;
+
+typedef struct _XGI_HEAP {
+       XGI_OH oh_free;
+       XGI_OH oh_used;
+       XGI_OH *poh_freelist;
+       XGI_OHALLOC *poha_chain;
+       unsigned long max_freesize;
+} XGI_HEAP;
+
+static unsigned long XGIfb_hwcursor_vbase;
+
+static unsigned long XGIfb_heap_start;
+static unsigned long XGIfb_heap_end;
+static unsigned long XGIfb_heap_size;
+static XGI_HEAP      XGIfb_heap;
+
+// Eden Chen
+static const struct _XGI_TV_filter {
+       u8 filter[9][4];
+} XGI_TV_filter[] = {
+       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_0 */
+          {0x00,0xE0,0x10,0x60},
+          {0x00,0xEE,0x10,0x44},
+          {0x00,0xF4,0x10,0x38},
+          {0xF8,0xF4,0x18,0x38},
+          {0xFC,0xFB,0x14,0x2A},
+          {0x00,0x00,0x10,0x20},
+          {0x00,0x04,0x10,0x18},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_1 */
+          {0x00,0xE0,0x10,0x60},
+          {0x00,0xEE,0x10,0x44},
+          {0x00,0xF4,0x10,0x38},
+          {0xF8,0xF4,0x18,0x38},
+          {0xFC,0xFB,0x14,0x2A},
+          {0x00,0x00,0x10,0x20},
+          {0x00,0x04,0x10,0x18},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_2 */
+          {0xF5,0xEE,0x1B,0x44},
+          {0xF8,0xF4,0x18,0x38},
+          {0xEB,0x04,0x25,0x18},
+          {0xF1,0x05,0x1F,0x16},
+          {0xF6,0x06,0x1A,0x14},
+          {0xFA,0x06,0x16,0x14},
+          {0x00,0x04,0x10,0x18},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_3 */
+          {0xF1,0x04,0x1F,0x18},
+          {0xEE,0x0D,0x22,0x06},
+          {0xF7,0x06,0x19,0x14},
+          {0xF4,0x0B,0x1C,0x0A},
+          {0xFA,0x07,0x16,0x12},
+          {0xF9,0x0A,0x17,0x0C},
+          {0x00,0x07,0x10,0x12},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_4 */
+          {0x00,0xE0,0x10,0x60},
+          {0x00,0xEE,0x10,0x44},
+          {0x00,0xF4,0x10,0x38},
+          {0xF8,0xF4,0x18,0x38},
+          {0xFC,0xFB,0x14,0x2A},
+          {0x00,0x00,0x10,0x20},
+          {0x00,0x04,0x10,0x18},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_5 */
+          {0xF5,0xEE,0x1B,0x44},
+          {0xF8,0xF4,0x18,0x38},
+          {0xEB,0x04,0x25,0x18},
+          {0xF1,0x05,0x1F,0x16},
+          {0xF6,0x06,0x1A,0x14},
+          {0xFA,0x06,0x16,0x14},
+          {0x00,0x04,0x10,0x18},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_6 */
+          {0xEB,0x04,0x25,0x18},
+          {0xE7,0x0E,0x29,0x04},
+          {0xEE,0x0C,0x22,0x08},
+          {0xF6,0x0B,0x1A,0x0A},
+          {0xF9,0x0A,0x17,0x0C},
+          {0xFC,0x0A,0x14,0x0C},
+          {0x00,0x08,0x10,0x10},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_7 */
+          {0xEC,0x02,0x24,0x1C},
+          {0xF2,0x04,0x1E,0x18},
+          {0xEB,0x15,0x25,0xF6},
+          {0xF4,0x10,0x1C,0x00},
+          {0xF8,0x0F,0x18,0x02},
+          {0x00,0x04,0x10,0x18},
+          {0x01,0x06,0x0F,0x14},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* PALFilter_0 */
+          {0x00,0xE0,0x10,0x60},
+          {0x00,0xEE,0x10,0x44},
+          {0x00,0xF4,0x10,0x38},
+          {0xF8,0xF4,0x18,0x38},
+          {0xFC,0xFB,0x14,0x2A},
+          {0x00,0x00,0x10,0x20},
+          {0x00,0x04,0x10,0x18},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* PALFilter_1 */
+          {0x00,0xE0,0x10,0x60},
+          {0x00,0xEE,0x10,0x44},
+          {0x00,0xF4,0x10,0x38},
+          {0xF8,0xF4,0x18,0x38},
+          {0xFC,0xFB,0x14,0x2A},
+          {0x00,0x00,0x10,0x20},
+          {0x00,0x04,0x10,0x18},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* PALFilter_2 */
+          {0xF5,0xEE,0x1B,0x44},
+          {0xF8,0xF4,0x18,0x38},
+          {0xF1,0xF7,0x01,0x32},
+          {0xF5,0xFB,0x1B,0x2A},
+          {0xF9,0xFF,0x17,0x22},
+          {0xFB,0x01,0x15,0x1E},
+          {0x00,0x04,0x10,0x18},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* PALFilter_3 */
+          {0xF5,0xFB,0x1B,0x2A},
+          {0xEE,0xFE,0x22,0x24},
+          {0xF3,0x00,0x1D,0x20},
+          {0xF9,0x03,0x17,0x1A},
+          {0xFB,0x02,0x14,0x1E},
+          {0xFB,0x04,0x15,0x18},
+          {0x00,0x06,0x10,0x14},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* PALFilter_4 */
+          {0x00,0xE0,0x10,0x60},
+          {0x00,0xEE,0x10,0x44},
+          {0x00,0xF4,0x10,0x38},
+          {0xF8,0xF4,0x18,0x38},
+          {0xFC,0xFB,0x14,0x2A},
+          {0x00,0x00,0x10,0x20},
+          {0x00,0x04,0x10,0x18},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* PALFilter_5 */
+          {0xF5,0xEE,0x1B,0x44},
+          {0xF8,0xF4,0x18,0x38},
+          {0xF1,0xF7,0x1F,0x32},
+          {0xF5,0xFB,0x1B,0x2A},
+          {0xF9,0xFF,0x17,0x22},
+          {0xFB,0x01,0x15,0x1E},
+          {0x00,0x04,0x10,0x18},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* PALFilter_6 */
+          {0xF5,0xEE,0x1B,0x2A},
+          {0xEE,0xFE,0x22,0x24},
+          {0xF3,0x00,0x1D,0x20},
+          {0xF9,0x03,0x17,0x1A},
+          {0xFB,0x02,0x14,0x1E},
+          {0xFB,0x04,0x15,0x18},
+          {0x00,0x06,0x10,0x14},
+          {0xFF,0xFF,0xFF,0xFF} }},
+       { {{0x00,0x00,0x00,0x40},  /* PALFilter_7 */
+          {0xF5,0xEE,0x1B,0x44},
+          {0xF8,0xF4,0x18,0x38},
+          {0xFC,0xFB,0x14,0x2A},
+          {0xEB,0x05,0x25,0x16},
+          {0xF1,0x05,0x1F,0x16},
+          {0xFA,0x07,0x16,0x12},
+          {0x00,0x07,0x10,0x12},
+          {0xFF,0xFF,0xFF,0xFF} }}
+};
+
+static int           filter = -1;
+static unsigned char filter_tb;
+
+
+/* ---------------------- Routine prototypes ------------------------- */
+
+/* Interface used by the world */
+#ifndef MODULE
+XGIINITSTATIC int __init XGIfb_setup(char *options);
+#endif
+
+/* Interface to the low level console driver */
+
+
+
+/* fbdev routines */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+       int     XGIfb_init(void);
+static int      XGIfb_get_fix(struct fb_fix_screeninfo *fix,
+                             int con,
+                             struct fb_info *info);
+static int      XGIfb_get_var(struct fb_var_screeninfo *var,
+                             int con,
+                             struct fb_info *info);
+static int      XGIfb_set_var(struct fb_var_screeninfo *var,
+                             int con,
+                             struct fb_info *info);
+static void     XGIfb_crtc_to_var(struct fb_var_screeninfo *var);
+static int      XGIfb_get_cmap(struct fb_cmap *cmap,
+                              int kspc,
+                              int con,
+                              struct fb_info *info);
+static int      XGIfb_set_cmap(struct fb_cmap *cmap,
+                              int kspc,
+                              int con,
+                              struct fb_info *info);
+static int      XGIfb_update_var(int con,
+                                struct fb_info *info);
+static int      XGIfb_switch(int con,
+                            struct fb_info *info);
+static void     XGIfb_blank(int blank,
+                           struct fb_info *info);
+static void     XGIfb_set_disp(int con,
+                              struct fb_var_screeninfo *var,
+                               struct fb_info *info);
+static int      XGI_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+                             unsigned *blue, unsigned *transp,
+                             struct fb_info *fb_info);
+static void     XGIfb_do_install_cmap(int con,
+                                      struct fb_info *info);
+static void     XGI_get_glyph(struct fb_info *info,
+                              XGI_GLYINFO *gly);
+static int     XGIfb_mmap(struct fb_info *info, struct file *file,
+                          struct vm_area_struct *vma);
+static int      XGIfb_ioctl(struct inode *inode, struct file *file,
+                           unsigned int cmd, unsigned long arg, int con,
+                           struct fb_info *info);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+XGIINITSTATIC int __init xgifb_init(void);
+static int      XGIfb_set_par(struct fb_info *info);
+static int      XGIfb_blank(int blank,
+                            struct fb_info *info);
+/*static int   XGIfb_mmap(struct fb_info *info, struct file *file,
+                          struct vm_area_struct *vma);
+*/
+extern void     fbcon_XGI_fillrect(struct fb_info *info,
+                                   const struct fb_fillrect *rect);
+extern void     fbcon_XGI_copyarea(struct fb_info *info,
+                                   const struct fb_copyarea *area);
+#if 0
+extern void     cfb_imageblit(struct fb_info *info,
+                              const struct fb_image *image);
+#endif
+extern int      fbcon_XGI_sync(struct fb_info *info);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
+                           unsigned long arg);
+#else
+static int      XGIfb_ioctl(struct inode *inode,
+                           struct file *file,
+                           unsigned int cmd,
+                           unsigned long arg,
+                           struct fb_info *info);
+#endif
+
+/*
+extern int     XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr,
+                             PXGI_HW_DEVICE_INFO HwDeviceExtension,
+                             unsigned char modeno, unsigned char rateindex);
+extern int      XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
+                        unsigned char modeno, unsigned char rateindex,
+                        unsigned int *left_margin, unsigned int *right_margin,
+                        unsigned int *upper_margin, unsigned int *lower_margin,
+                        unsigned int *hsync_len, unsigned int *vsync_len,
+                        unsigned int *sync, unsigned int *vmode);
+*/
+#endif
+                       extern   BOOLEAN  XGI_SearchModeID( USHORT ModeNo,USHORT  *ModeIdIndex, PVB_DEVICE_INFO );
+static int      XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+                             struct fb_info *info);
+
+/* Internal 2D accelerator functions */
+extern int      XGIfb_initaccel(void);
+extern void     XGIfb_syncaccel(void);
+
+/* Internal general routines */
+static void     XGIfb_search_mode(const char *name);
+static int      XGIfb_validate_mode(int modeindex);
+static u8       XGIfb_search_refresh_rate(unsigned int rate);
+static int      XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                       unsigned blue, unsigned transp,
+                       struct fb_info *fb_info);
+static int      XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+                       struct fb_info *info);
+static void     XGIfb_pre_setmode(void);
+static void     XGIfb_post_setmode(void);
+
+static BOOLEAN  XGIfb_CheckVBRetrace(void);
+static BOOLEAN  XGIfbcheckvretracecrt2(void);
+static BOOLEAN  XGIfbcheckvretracecrt1(void);
+static BOOLEAN  XGIfb_bridgeisslave(void);
+
+struct XGI_memreq {
+       unsigned long offset;
+       unsigned long size;
+};
+
+/* XGI-specific Export functions */
+void            XGI_dispinfo(struct ap_data *rec);
+void            XGI_malloc(struct XGI_memreq *req);
+void            XGI_free(unsigned long base);
+
+/* Internal hardware access routines */
+void            XGIfb_set_reg4(u16 port, unsigned long data);
+u32             XGIfb_get_reg3(u16 port);
+
+/* Chipset-dependent internal routines */
+
+
+static int      XGIfb_get_dram_size(void);
+static void     XGIfb_detect_VB(void);
+static void     XGIfb_get_VB_type(void);
+static int      XGIfb_has_VB(void);
+
+
+/* Internal heap routines */
+static int      XGIfb_heap_init(void);
+static XGI_OH   *XGIfb_poh_new_node(void);
+static XGI_OH   *XGIfb_poh_allocate(unsigned long size);
+static void     XGIfb_delete_node(XGI_OH *poh);
+static void     XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh);
+static XGI_OH   *XGIfb_poh_free(unsigned long base);
+static void     XGIfb_free_node(XGI_OH *poh);
+
+/* Internal routines to access PCI configuration space */
+BOOLEAN         XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+                       unsigned long offset, unsigned long set, unsigned long *value);
+//BOOLEAN         XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+//                     unsigned long offset, unsigned long set, unsigned long *value);
+
+
+/* Routines from init.c/init301.c */
+extern void     InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo);
+extern BOOLEAN  XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension);
+extern BOOLEAN  XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo);
+//extern void     XGI_SetEnableDstn(VB_DEVICE_INFO *XGI_Pr);
+extern void     XGI_LongWait(VB_DEVICE_INFO *XGI_Pr);
+extern USHORT   XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
+/* TW: Chrontel TV functions */
+extern USHORT  XGI_GetCH700x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+extern void    XGI_SetCH700x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+extern USHORT  XGI_GetCH701x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+extern void    XGI_SetCH701x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+extern void     XGI_SetCH70xxANDOR(VB_DEVICE_INFO *XGI_Pr, USHORT tempax,USHORT tempbh);
+extern void     XGI_DDC2Delay(VB_DEVICE_INFO *XGI_Pr, USHORT delaytime);
+
+/* TW: Sensing routines */
+void            XGI_Sense30x(void);
+int             XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch);
+
+extern XGI21_LVDSCapStruct XGI21_LCDCapList[13];
+#endif
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
new file mode 100644 (file)
index 0000000..867012b
--- /dev/null
@@ -0,0 +1,3773 @@
+/*
+ * XG20, XG21, XG40, XG42 frame buffer device
+ * for Linux kernels  2.5.x, 2.6.x
+ * Base on TW's sis fbdev code.
+ */
+
+//#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/vt_kern.h>
+#include <linux/capability.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/kernel.h>
+
+#include "osdef.h"
+
+
+#ifndef XGIFB_PAN
+#define XGIFB_PAN
+#endif
+
+#include <asm/io.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "XGIfb.h"
+#include "vgatypes.h"
+#include "XGI_main.h"
+#include "vb_util.h"
+
+
+#define Index_CR_GPIO_Reg1 0x48
+#define Index_CR_GPIO_Reg2 0x49
+#define Index_CR_GPIO_Reg3 0x4a
+
+#define GPIOG_EN    (1<<6)
+#define GPIOG_WRITE (1<<6)
+#define GPIOG_READ  (1<<1)
+int XGIfb_GetXG21DefaultLVDSModeIdx(void);
+
+/* -------------------- Macro definitions ---------------------------- */
+
+#undef XGIFBDEBUG
+
+#ifdef XGIFBDEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#ifdef XGIFBDEBUG
+static void dumpVGAReg(void)
+{
+    u8 i,reg;
+
+outXGIIDXREG(XGISR, 0x05, 0x86);
+/*
+outXGIIDXREG(XGISR, 0x08, 0x4f);
+outXGIIDXREG(XGISR, 0x0f, 0x20);
+outXGIIDXREG(XGISR, 0x11, 0x4f);
+outXGIIDXREG(XGISR, 0x13, 0x45);
+outXGIIDXREG(XGISR, 0x14, 0x51);
+outXGIIDXREG(XGISR, 0x1e, 0x41);
+outXGIIDXREG(XGISR, 0x1f, 0x0);
+outXGIIDXREG(XGISR, 0x20, 0xa1);
+outXGIIDXREG(XGISR, 0x22, 0xfb);
+outXGIIDXREG(XGISR, 0x26, 0x22);
+outXGIIDXREG(XGISR, 0x3e, 0x07);
+*/
+
+//outXGIIDXREG(XGICR, 0x19, 0x00);
+//outXGIIDXREG(XGICR, 0x1a, 0x3C);
+//outXGIIDXREG(XGICR, 0x22, 0xff);
+//outXGIIDXREG(XGICR, 0x3D, 0x10);
+
+//outXGIIDXREG(XGICR, 0x4a, 0xf3);
+
+//outXGIIDXREG(XGICR, 0x57, 0x0);
+//outXGIIDXREG(XGICR, 0x7a, 0x2c);
+
+//outXGIIDXREG(XGICR, 0x82, 0xcc);
+//outXGIIDXREG(XGICR, 0x8c, 0x0);
+/*
+outXGIIDXREG(XGICR, 0x99, 0x1);
+outXGIIDXREG(XGICR, 0x41, 0x40);
+*/
+
+    for(i=0; i < 0x4f; i++)
+    {
+        inXGIIDXREG(XGISR, i, reg);
+        printk("\no 3c4 %x",i);
+        printk("\ni 3c5 => %x",reg);
+    }
+
+    for(i=0; i < 0xF0; i++)
+    {
+        inXGIIDXREG(XGICR, i, reg);
+        printk("\no 3d4 %x",i);
+        printk("\ni 3d5 => %x",reg);
+    }
+/*
+
+    outXGIIDXREG(XGIPART1,0x2F,1);
+    for(i=1; i < 0x50; i++)
+    {
+        inXGIIDXREG(XGIPART1, i, reg);
+        printk("\no d004 %x",i);
+        printk("\ni d005 => %x",reg);
+    }
+
+    for(i=0; i < 0x50; i++)
+    {
+        inXGIIDXREG(XGIPART2, i, reg);
+        printk("\no d010 %x",i);
+        printk("\ni d011 => %x",reg);
+    }
+    for(i=0; i < 0x50; i++)
+    {
+        inXGIIDXREG(XGIPART3, i, reg);
+        printk("\no d012 %x",i);
+        printk("\ni d013 => %x",reg);
+    }
+    for(i=0; i < 0x50; i++)
+    {
+        inXGIIDXREG(XGIPART4, i, reg);
+        printk("\no d014 %x",i);
+        printk("\ni d015 => %x",reg);
+    }
+*/
+}
+#else
+static inline void dumpVGAReg(void) {}
+#endif
+
+/* data for XGI components */
+struct video_info  xgi_video_info;
+
+
+#if 1
+#define DEBUGPRN(x)
+#else
+#define DEBUGPRN(x) printk(KERN_INFO x "\n");
+#endif
+
+
+/* --------------- Hardware Access Routines -------------------------- */
+
+#ifdef LINUX_KERNEL
+int
+XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
+                         unsigned char modeno, unsigned char rateindex)
+{
+    USHORT ModeNo = modeno;
+    USHORT ModeIdIndex = 0, ClockIndex = 0;
+    USHORT RefreshRateTableIndex = 0;
+
+    /*ULONG  temp = 0;*/
+    int    Clock;
+    XGI_Pr->ROMAddr  = HwDeviceExtension->pjVirtualRomBase;
+    InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
+
+    RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
+
+/*
+    temp = XGI_SearchModeID( ModeNo , &ModeIdIndex,  XGI_Pr ) ;
+    if(!temp) {
+       printk(KERN_ERR "Could not find mode %x\n", ModeNo);
+       return 65000;
+    }
+
+    RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
+    RefreshRateTableIndex += (rateindex - 1);
+
+*/
+    ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+    if(HwDeviceExtension->jChipType < XGI_315H) {
+       ClockIndex &= 0x3F;
+    }
+    Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000 ;
+
+    return(Clock);
+}
+
+int
+XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
+                        unsigned char modeno, unsigned char rateindex,
+                        u32 *left_margin, u32 *right_margin,
+                        u32 *upper_margin, u32 *lower_margin,
+                        u32 *hsync_len, u32 *vsync_len,
+                        u32 *sync, u32 *vmode)
+{
+    USHORT ModeNo = modeno;
+    USHORT ModeIdIndex = 0, index = 0;
+    USHORT RefreshRateTableIndex = 0;
+
+    unsigned short VRE, VBE, VRS, VBS, VDE, VT;
+    unsigned short HRE, HBE, HRS, HBS, HDE, HT;
+    unsigned char  sr_data, cr_data, cr_data2;
+    unsigned long cr_data3;
+    int            A, B, C, D, E, F, temp, j;
+    XGI_Pr->ROMAddr  = HwDeviceExtension->pjVirtualRomBase;
+    InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
+  RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
+/*
+    temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr);
+    if(!temp) return 0;
+
+    RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
+    RefreshRateTableIndex += (rateindex - 1);
+*/
+    index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+
+    sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
+
+    cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
+
+    /* Horizontal total */
+    HT = (cr_data & 0xff) |
+         ((unsigned short) (sr_data & 0x03) << 8);
+    A = HT + 5;
+
+    /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
+
+     Horizontal display enable end
+    HDE = (cr_data & 0xff) |
+          ((unsigned short) (sr_data & 0x0C) << 6);*/
+    HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) -1;
+    E = HDE + 1;
+
+    cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
+
+    /* Horizontal retrace (=sync) start */
+    HRS = (cr_data & 0xff) |
+          ((unsigned short) (sr_data & 0xC0) << 2);
+    F = HRS - E - 3;
+
+    cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
+
+    /* Horizontal blank start */
+    HBS = (cr_data & 0xff) |
+          ((unsigned short) (sr_data & 0x30) << 4);
+
+    sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
+
+    cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
+
+    cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
+
+    /* Horizontal blank end */
+    HBE = (cr_data & 0x1f) |
+          ((unsigned short) (cr_data2 & 0x80) >> 2) |
+         ((unsigned short) (sr_data & 0x03) << 6);
+
+    /* Horizontal retrace (=sync) end */
+    HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
+
+    temp = HBE - ((E - 1) & 255);
+    B = (temp > 0) ? temp : (temp + 256);
+
+    temp = HRE - ((E + F + 3) & 63);
+    C = (temp > 0) ? temp : (temp + 64);
+
+    D = B - F - C;
+
+    *left_margin = D * 8;
+    *right_margin = F * 8;
+    *hsync_len = C * 8;
+
+    sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
+
+    cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
+
+    cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
+
+    /* Vertical total */
+    VT = (cr_data & 0xFF) |
+         ((unsigned short) (cr_data2 & 0x01) << 8) |
+        ((unsigned short)(cr_data2 & 0x20) << 4) |
+        ((unsigned short) (sr_data & 0x01) << 10);
+    A = VT + 2;
+
+    //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
+
+    /* Vertical display enable end */
+/*    VDE = (cr_data & 0xff) |
+          ((unsigned short) (cr_data2 & 0x02) << 7) |
+         ((unsigned short) (cr_data2 & 0x40) << 3) |
+         ((unsigned short) (sr_data & 0x02) << 9); */
+    VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes  -1;
+    E = VDE + 1;
+
+    cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
+
+    /* Vertical retrace (=sync) start */
+    VRS = (cr_data & 0xff) |
+          ((unsigned short) (cr_data2 & 0x04) << 6) |
+         ((unsigned short) (cr_data2 & 0x80) << 2) |
+         ((unsigned short) (sr_data & 0x08) << 7);
+    F = VRS + 1 - E;
+
+    cr_data =  XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
+
+    cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
+
+    /* Vertical blank start */
+    VBS = (cr_data & 0xff) |
+          ((unsigned short) (cr_data2 & 0x08) << 5) |
+         ((unsigned short) (cr_data3 & 0x20) << 4) |
+         ((unsigned short) (sr_data & 0x04) << 8);
+
+    cr_data =  XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
+
+    /* Vertical blank end */
+    VBE = (cr_data & 0xff) |
+          ((unsigned short) (sr_data & 0x10) << 4);
+    temp = VBE - ((E - 1) & 511);
+    B = (temp > 0) ? temp : (temp + 512);
+
+    cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
+
+    /* Vertical retrace (=sync) end */
+    VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
+    temp = VRE - ((E + F - 1) & 31);
+    C = (temp > 0) ? temp : (temp + 32);
+
+    D = B - F - C;
+
+    *upper_margin = D;
+    *lower_margin = F;
+    *vsync_len = C;
+
+    if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
+       *sync &= ~FB_SYNC_VERT_HIGH_ACT;
+    else
+       *sync |= FB_SYNC_VERT_HIGH_ACT;
+
+    if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
+       *sync &= ~FB_SYNC_HOR_HIGH_ACT;
+    else
+       *sync |= FB_SYNC_HOR_HIGH_ACT;
+
+    *vmode = FB_VMODE_NONINTERLACED;
+    if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
+       *vmode = FB_VMODE_INTERLACED;
+    else {
+      j = 0;
+      while(XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
+          if(XGI_Pr->EModeIDTable[j].Ext_ModeID ==
+                         XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
+              if(XGI_Pr->EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
+                 *vmode = FB_VMODE_DOUBLE;
+              }
+             break;
+          }
+         j++;
+      }
+    }
+
+#if 0  /* That's bullshit, only the resolution needs to be shifted */
+    if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+       *upper_margin <<= 1;
+       *lower_margin <<= 1;
+       *vsync_len <<= 1;
+    } else if((*vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+       *upper_margin >>= 1;
+       *lower_margin >>= 1;
+       *vsync_len >>= 1;
+    }
+#endif
+
+    return 1;
+}
+
+#endif
+
+
+
+void XGIRegInit(VB_DEVICE_INFO *XGI_Pr, ULONG BaseAddr)
+{
+   XGI_Pr->RelIO = BaseAddr;
+   XGI_Pr->P3c4 = BaseAddr + 0x14;
+   XGI_Pr->P3d4 = BaseAddr + 0x24;
+   XGI_Pr->P3c0 = BaseAddr + 0x10;
+   XGI_Pr->P3ce = BaseAddr + 0x1e;
+   XGI_Pr->P3c2 = BaseAddr + 0x12;
+   XGI_Pr->P3ca = BaseAddr + 0x1a;
+   XGI_Pr->P3c6 = BaseAddr + 0x16;
+   XGI_Pr->P3c7 = BaseAddr + 0x17;
+   XGI_Pr->P3c8 = BaseAddr + 0x18;
+   XGI_Pr->P3c9 = BaseAddr + 0x19;
+   XGI_Pr->P3da = BaseAddr + 0x2A;
+   XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04;   /* Digital video interface registers (LCD) */
+   XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10;   /* 301 TV Encoder registers */
+   XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12;   /* 301 Macrovision registers */
+   XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14;   /* 301 VGA2 (and LCD) registers */
+   XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14+2; /* 301 palette address port registers */
+
+}
+
+
+void XGIfb_set_reg4(u16 port, unsigned long data)
+{
+       outl((u32) (data & 0xffffffff), port);
+}
+
+u32 XGIfb_get_reg3(u16 port)
+{
+       u32 data;
+
+       data = inl(port);
+       return (data);
+}
+
+/* ------------ Interface for init & mode switching code ------------- */
+
+BOOLEAN
+XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+       unsigned long offset, unsigned long set, unsigned long *value)
+{
+       static struct pci_dev *pdev = NULL;
+       static unsigned char init = 0, valid_pdev = 0;
+
+       if (!set)
+               DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
+       else
+               DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
+
+       if (!init) {
+               init = TRUE;
+               pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id, pdev);
+               if (pdev) {
+                       valid_pdev = TRUE;
+                       pci_dev_put(pdev);
+               }
+       }
+
+       if (!valid_pdev) {
+               printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
+                               xgi_video_info.chip_id);
+               return FALSE;
+       }
+
+       if (set == 0)
+               pci_read_config_dword(pdev, offset, (u32 *)value);
+       else
+               pci_write_config_dword(pdev, offset, (u32)(*value));
+
+       return TRUE;
+}
+
+/*BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+       unsigned long offset, unsigned long set, unsigned long *value)
+{
+       static struct pci_dev *pdev = NULL;
+       static unsigned char init = 0, valid_pdev = 0;
+       u16 nbridge_id = 0;
+
+       if (!init) {
+               init = TRUE;
+               switch (xgi_video_info.chip) {
+               case XGI_540:
+                       nbridge_id = PCI_DEVICE_ID_XG_540;
+                       break;
+               case XGI_630:
+                       nbridge_id = PCI_DEVICE_ID_XG_630;
+                       break;
+               case XGI_730:
+                       nbridge_id = PCI_DEVICE_ID_XG_730;
+                       break;
+               case XGI_550:
+                       nbridge_id = PCI_DEVICE_ID_XG_550;
+                       break;
+               case XGI_650:
+                       nbridge_id = PCI_DEVICE_ID_XG_650;
+                       break;
+               case XGI_740:
+                       nbridge_id = PCI_DEVICE_ID_XG_740;
+                       break;
+               default:
+                       nbridge_id = 0;
+                       break;
+               }
+
+               pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
+               if (pdev)
+                       valid_pdev = TRUE;
+       }
+
+       if (!valid_pdev) {
+               printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
+                               nbridge_id);
+               return FALSE;
+       }
+
+       if (set == 0)
+               pci_read_config_dword(pdev, offset, (u32 *)value);
+       else
+               pci_write_config_dword(pdev, offset, (u32)(*value));
+
+       return TRUE;
+}
+*/
+/* ------------------ Internal helper routines ----------------- */
+
+static void XGIfb_search_mode(const char *name)
+{
+       int i = 0, j = 0, l;
+
+       if(name == NULL) {
+          printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
+          xgifb_mode_idx = DEFAULT_MODE;
+          if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
+          {
+              xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
+          }
+          return;
+       }
+
+
+        if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
+          printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
+          xgifb_mode_idx = DEFAULT_MODE;
+          if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
+          {
+              xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
+          }
+          return;
+       }
+
+       while(XGIbios_mode[i].mode_no != 0) {
+               l = min(strlen(name), strlen(XGIbios_mode[i].name));
+               if (!strncmp(name, XGIbios_mode[i].name, l)) {
+                       xgifb_mode_idx = i;
+                       j = 1;
+                       break;
+               }
+               i++;
+       }
+       if(!j) printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
+}
+
+static void XGIfb_search_vesamode(unsigned int vesamode)
+{
+       int i = 0, j = 0;
+
+       if(vesamode == 0) {
+
+               printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
+               xgifb_mode_idx = DEFAULT_MODE;
+               if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
+               {
+                   xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
+               }
+               return;
+       }
+
+       vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
+
+       while(XGIbios_mode[i].mode_no != 0) {
+               if( (XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
+                   (XGIbios_mode[i].vesa_mode_no_2 == vesamode) ) {
+                       xgifb_mode_idx = i;
+                       j = 1;
+                       break;
+               }
+               i++;
+       }
+       if(!j) printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
+}
+
+int XGIfb_GetXG21LVDSData(void)
+{
+    u8 tmp;
+    unsigned char *pData;
+    int i,j,k;
+
+    inXGIIDXREG(XGISR,0x1e,tmp);
+    outXGIIDXREG(XGISR, 0x1e, tmp|4);
+
+    pData = xgi_video_info.mmio_vbase+0x20000;
+    if ((pData[0x0]==0x55) && (pData[0x1]==0xAA) && (pData[0x65] & 0x1))
+    {
+        i = pData[ 0x316 ] | ( pData[ 0x317 ] << 8 );
+        j = pData[ i-1 ] ;
+        if ( j == 0xff )
+        {
+         j = 1;
+       }
+        k = 0;
+        do
+        {
+                XGI21_LCDCapList[k].LVDS_Capability = pData[ i ] | ( pData[ i + 1 ] << 8 );
+                XGI21_LCDCapList[k].LVDSHT = pData[ i + 2 ] | ( pData[ i + 3 ] << 8 ) ;
+                XGI21_LCDCapList[k].LVDSVT = pData[ i + 4 ] | ( pData[ i + 5 ] << 8 );
+                XGI21_LCDCapList[k].LVDSHDE = pData[ i + 6 ] | ( pData[ i + 7 ] << 8 );
+                XGI21_LCDCapList[k].LVDSVDE = pData[ i + 8 ] | ( pData[ i + 9 ] << 8 );
+                XGI21_LCDCapList[k].LVDSHFP = pData[ i + 10 ] | ( pData[ i + 11 ] << 8 );
+                XGI21_LCDCapList[k].LVDSVFP = pData[ i + 12 ] | ( pData[ i + 13 ] << 8 );
+                XGI21_LCDCapList[k].LVDSHSYNC = pData[ i + 14 ] | ( pData[ i + 15 ] << 8 );
+                XGI21_LCDCapList[k].LVDSVSYNC = pData[ i + 16 ] | ( pData[ i + 17 ] << 8 );
+                XGI21_LCDCapList[k].VCLKData1 = pData[ i + 18 ] ;
+                XGI21_LCDCapList[k].VCLKData2 = pData[ i + 19 ] ;
+                XGI21_LCDCapList[k].PSC_S1 = pData[ i + 20 ] ;
+                XGI21_LCDCapList[k].PSC_S2 = pData[ i + 21 ] ;
+                XGI21_LCDCapList[k].PSC_S3 = pData[ i + 22 ] ;
+                XGI21_LCDCapList[k].PSC_S4 = pData[ i + 23 ] ;
+                XGI21_LCDCapList[k].PSC_S5 = pData[ i + 24 ] ;
+                i += 25;
+                j--;
+                k++;
+        } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) );
+        return 1;
+    }
+    return 0;
+}
+
+int XGIfb_GetXG21DefaultLVDSModeIdx(void)
+{
+
+       int found_mode = 0;
+       int XGIfb_mode_idx = 0;
+
+       found_mode = 0;
+       while( (XGIbios_mode[XGIfb_mode_idx].mode_no != 0) &&
+              (XGIbios_mode[XGIfb_mode_idx].xres <= XGI21_LCDCapList[0].LVDSHDE) )
+       {
+               if( (XGIbios_mode[XGIfb_mode_idx].xres == XGI21_LCDCapList[0].LVDSHDE) &&
+                   (XGIbios_mode[XGIfb_mode_idx].yres == XGI21_LCDCapList[0].LVDSVDE) &&
+                   (XGIbios_mode[XGIfb_mode_idx].bpp == 8))
+               {
+                       XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
+                       found_mode = 1;
+                       break;
+               }
+               XGIfb_mode_idx++;
+       }
+        if (!found_mode)
+         XGIfb_mode_idx = 0;
+
+       return (XGIfb_mode_idx);
+}
+
+
+static int XGIfb_validate_mode(int myindex)
+{
+   u16 xres, yres;
+
+    if (xgi_video_info.chip == XG21)
+    {
+        if ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)
+        {
+           xres = XGI21_LCDCapList[0].LVDSHDE;
+           yres = XGI21_LCDCapList[0].LVDSVDE;
+           if(XGIbios_mode[myindex].xres > xres)
+               return(-1);
+            if(XGIbios_mode[myindex].yres > yres)
+               return(-1);
+            if ((XGIbios_mode[myindex].xres < xres) && (XGIbios_mode[myindex].yres < yres) )
+           {
+              if (XGIbios_mode[myindex].bpp > 8)
+                 return(-1);
+           }
+
+       }
+       return(myindex);
+
+    }
+
+    /* FIXME: for now, all is valid on XG27 */
+    if (xgi_video_info.chip == XG27)
+           return(myindex);
+
+    if(!(XGIbios_mode[myindex].chipset & MD_XGI315))
+        return(-1);
+
+   switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+     case DISPTYPE_LCD:
+       switch (XGIhw_ext.ulCRT2LCDType) {
+       case LCD_640x480:
+               xres =  640; yres =  480;  break;
+       case LCD_800x600:
+               xres =  800; yres =  600;  break;
+        case LCD_1024x600:
+               xres = 1024; yres =  600;  break;
+       case LCD_1024x768:
+               xres = 1024; yres =  768;  break;
+       case LCD_1152x768:
+               xres = 1152; yres =  768;  break;
+       case LCD_1280x960:
+               xres = 1280; yres =  960;  break;
+       case LCD_1280x768:
+               xres = 1280; yres =  768;  break;
+       case LCD_1280x1024:
+               xres = 1280; yres = 1024;  break;
+       case LCD_1400x1050:
+               xres = 1400; yres = 1050;  break;
+       case LCD_1600x1200:
+               xres = 1600; yres = 1200;  break;
+//     case LCD_320x480:                               // TW: FSTN
+//             xres =  320; yres =  480;  break;
+       default:
+               xres =    0; yres =    0;  break;
+       }
+       if(XGIbios_mode[myindex].xres > xres) {
+               return(-1);
+       }
+        if(XGIbios_mode[myindex].yres > yres) {
+               return(-1);
+       }
+       if((XGIhw_ext.ulExternalChip == 0x01) ||   // LVDS
+           (XGIhw_ext.ulExternalChip == 0x05))    // LVDS+Chrontel
+       {
+          switch (XGIbios_mode[myindex].xres) {
+               case 512:
+                       if(XGIbios_mode[myindex].yres != 512) return -1;
+                       if(XGIhw_ext.ulCRT2LCDType == LCD_1024x600) return -1;
+                       break;
+               case 640:
+                       if((XGIbios_mode[myindex].yres != 400) &&
+                          (XGIbios_mode[myindex].yres != 480))
+                               return -1;
+                       break;
+               case 800:
+                       if(XGIbios_mode[myindex].yres != 600) return -1;
+                       break;
+               case 1024:
+                       if((XGIbios_mode[myindex].yres != 600) &&
+                          (XGIbios_mode[myindex].yres != 768))
+                               return -1;
+                       if((XGIbios_mode[myindex].yres == 600) &&
+                          (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
+                               return -1;
+                       break;
+               case 1152:
+                       if((XGIbios_mode[myindex].yres) != 768) return -1;
+                       if(XGIhw_ext.ulCRT2LCDType != LCD_1152x768) return -1;
+                       break;
+               case 1280:
+                       if((XGIbios_mode[myindex].yres != 768) &&
+                          (XGIbios_mode[myindex].yres != 1024))
+                               return -1;
+                       if((XGIbios_mode[myindex].yres == 768) &&
+                          (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
+                               return -1;
+                       break;
+               case 1400:
+                       if(XGIbios_mode[myindex].yres != 1050) return -1;
+                       break;
+               case 1600:
+                       if(XGIbios_mode[myindex].yres != 1200) return -1;
+                       break;
+               default:
+                       return -1;
+          }
+       } else {
+          switch (XGIbios_mode[myindex].xres) {
+               case 512:
+                       if(XGIbios_mode[myindex].yres != 512) return -1;
+                       break;
+               case 640:
+                       if((XGIbios_mode[myindex].yres != 400) &&
+                          (XGIbios_mode[myindex].yres != 480))
+                               return -1;
+                       break;
+               case 800:
+                       if(XGIbios_mode[myindex].yres != 600) return -1;
+                       break;
+               case 1024:
+                       if(XGIbios_mode[myindex].yres != 768) return -1;
+                       break;
+               case 1280:
+                       if((XGIbios_mode[myindex].yres != 960) &&
+                          (XGIbios_mode[myindex].yres != 1024))
+                               return -1;
+                       if(XGIbios_mode[myindex].yres == 960) {
+                           if(XGIhw_ext.ulCRT2LCDType == LCD_1400x1050)
+                               return -1;
+                       }
+                       break;
+               case 1400:
+                       if(XGIbios_mode[myindex].yres != 1050) return -1;
+                       break;
+               case 1600:
+                       if(XGIbios_mode[myindex].yres != 1200) return -1;
+                       break;
+               default:
+                       return -1;
+          }
+       }
+       break;
+     case DISPTYPE_TV:
+       switch (XGIbios_mode[myindex].xres) {
+       case 512:
+       case 640:
+       case 800:
+               break;
+       case 720:
+               if (xgi_video_info.TV_type == TVMODE_NTSC) {
+                       if (XGIbios_mode[myindex].yres != 480) {
+                               return(-1);
+                       }
+               } else if (xgi_video_info.TV_type == TVMODE_PAL) {
+                       if (XGIbios_mode[myindex].yres != 576) {
+                               return(-1);
+                       }
+               }
+               // TW: LVDS/CHRONTEL does not support 720
+               if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
+                                       xgi_video_info.hasVB == HASVB_CHRONTEL) {
+                               return(-1);
+               }
+               break;
+       case 1024:
+               if (xgi_video_info.TV_type == TVMODE_NTSC) {
+                       if(XGIbios_mode[myindex].bpp == 32) {
+                              return(-1);
+                       }
+               }
+               // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)
+               if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
+                                       xgi_video_info.hasVB == HASVB_CHRONTEL) {
+                   if(xgi_video_info.chip < XGI_315H) {
+                               return(-1);
+                   }
+               }
+               break;
+       default:
+               return(-1);
+       }
+       break;
+     case DISPTYPE_CRT2:
+        if(XGIbios_mode[myindex].xres > 1280) return -1;
+       break;
+     }
+     return(myindex);
+
+}
+
+static void XGIfb_search_crt2type(const char *name)
+{
+       int i = 0;
+
+       if(name == NULL)
+               return;
+
+       while(XGI_crt2type[i].type_no != -1) {
+               if (!strcmp(name, XGI_crt2type[i].name)) {
+                       XGIfb_crt2type = XGI_crt2type[i].type_no;
+                       XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
+                       break;
+               }
+               i++;
+       }
+       if(XGIfb_crt2type < 0)
+               printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
+}
+
+static void XGIfb_search_queuemode(const char *name)
+{
+       int i = 0;
+
+       if(name == NULL)
+               return;
+
+       while (XGI_queuemode[i].type_no != -1) {
+               if (!strcmp(name, XGI_queuemode[i].name)) {
+                       XGIfb_queuemode = XGI_queuemode[i].type_no;
+                       break;
+               }
+               i++;
+       }
+       if (XGIfb_queuemode < 0)
+               printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
+}
+
+static u8 XGIfb_search_refresh_rate(unsigned int rate)
+{
+       u16 xres, yres;
+       int i = 0;
+
+       xres = XGIbios_mode[xgifb_mode_idx].xres;
+       yres = XGIbios_mode[xgifb_mode_idx].yres;
+
+       XGIfb_rate_idx = 0;
+       while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
+               if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres == yres)) {
+                       if (XGIfb_vrate[i].refresh == rate) {
+                               XGIfb_rate_idx = XGIfb_vrate[i].idx;
+                               break;
+                       } else if (XGIfb_vrate[i].refresh > rate) {
+                               if ((XGIfb_vrate[i].refresh - rate) <= 3) {
+                                       DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
+                                               rate, XGIfb_vrate[i].refresh);
+                                       XGIfb_rate_idx = XGIfb_vrate[i].idx;
+                                       xgi_video_info.refresh_rate = XGIfb_vrate[i].refresh;
+                               } else if (((rate - XGIfb_vrate[i-1].refresh) <= 2)
+                                               && (XGIfb_vrate[i].idx != 1)) {
+                                       DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
+                                               rate, XGIfb_vrate[i-1].refresh);
+                                       XGIfb_rate_idx = XGIfb_vrate[i-1].idx;
+                                       xgi_video_info.refresh_rate = XGIfb_vrate[i-1].refresh;
+                               }
+                               break;
+                       } else if((rate - XGIfb_vrate[i].refresh) <= 2) {
+                               DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
+                                               rate, XGIfb_vrate[i].refresh);
+                               XGIfb_rate_idx = XGIfb_vrate[i].idx;
+                               break;
+                       }
+               }
+               i++;
+       }
+       if (XGIfb_rate_idx > 0) {
+               return XGIfb_rate_idx;
+       } else {
+               printk(KERN_INFO
+                       "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
+               return 0;
+       }
+}
+
+static void XGIfb_search_tvstd(const char *name)
+{
+       int i = 0;
+
+       if(name == NULL)
+               return;
+
+       while (XGI_tvtype[i].type_no != -1) {
+               if (!strcmp(name, XGI_tvtype[i].name)) {
+                       XGIfb_tvmode = XGI_tvtype[i].type_no;
+                       break;
+               }
+               i++;
+       }
+}
+
+static BOOLEAN XGIfb_bridgeisslave(void)
+{
+   unsigned char usScratchP1_00;
+
+   if(xgi_video_info.hasVB == HASVB_NONE) return FALSE;
+
+   inXGIIDXREG(XGIPART1,0x00,usScratchP1_00);
+   if( (usScratchP1_00 & 0x50) == 0x10)  {
+          return TRUE;
+   } else {
+           return FALSE;
+   }
+}
+
+static BOOLEAN XGIfbcheckvretracecrt1(void)
+{
+   unsigned char temp;
+
+   inXGIIDXREG(XGICR,0x17,temp);
+   if(!(temp & 0x80)) return FALSE;
+
+
+   inXGIIDXREG(XGISR,0x1f,temp);
+   if(temp & 0xc0) return FALSE;
+
+
+   if(inXGIREG(XGIINPSTAT) & 0x08) return TRUE;
+   else                           return FALSE;
+}
+
+static BOOLEAN XGIfbcheckvretracecrt2(void)
+{
+   unsigned char temp;
+   if(xgi_video_info.hasVB == HASVB_NONE) return FALSE;
+   inXGIIDXREG(XGIPART1, 0x30, temp);
+   if(temp & 0x02) return FALSE;
+   else           return TRUE;
+}
+
+static BOOLEAN XGIfb_CheckVBRetrace(void)
+{
+   if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
+      if(XGIfb_bridgeisslave()) {
+         return(XGIfbcheckvretracecrt1());
+      } else {
+         return(XGIfbcheckvretracecrt2());
+      }
+   }
+   return(XGIfbcheckvretracecrt1());
+}
+
+/* ----------- FBDev related routines for all series ----------- */
+
+
+static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
+{
+       switch(var->bits_per_pixel) {
+          case 8:
+               var->red.offset = var->green.offset = var->blue.offset = 0;
+               var->red.length = var->green.length = var->blue.length = 6;
+               xgi_video_info.video_cmap_len = 256;
+               break;
+          case 16:
+               var->red.offset = 11;
+               var->red.length = 5;
+               var->green.offset = 5;
+               var->green.length = 6;
+               var->blue.offset = 0;
+               var->blue.length = 5;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               xgi_video_info.video_cmap_len = 16;
+               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;
+               xgi_video_info.video_cmap_len = 16;
+               break;
+       }
+}
+
+
+
+static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+                     struct fb_info *info)
+{
+
+       unsigned int htotal = var->left_margin + var->xres +
+               var->right_margin + var->hsync_len;
+       unsigned int vtotal = var->upper_margin + var->yres +
+               var->lower_margin + var->vsync_len;
+#if defined(__powerpc__)
+       u8 sr_data, cr_data;
+#endif
+       unsigned int drate = 0, hrate = 0;
+       int found_mode = 0;
+       int old_mode;
+//     unsigned char reg,reg1;
+
+       DEBUGPRN("Inside do_set_var");
+//        printk(KERN_DEBUG "XGIfb:var->yres=%d, var->upper_margin=%d, var->lower_margin=%d, var->vsync_len=%d\n", var->yres,var->upper_margin,var->lower_margin,var->vsync_len);
+
+        info->var.xres_virtual = var->xres_virtual;
+        info->var.yres_virtual = var->yres_virtual;
+        info->var.bits_per_pixel = var->bits_per_pixel;
+
+       if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
+               vtotal <<= 1;
+       else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
+               vtotal <<= 2;
+       else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+       {
+//             vtotal <<= 1;
+//             var->yres <<= 1;
+       }
+
+       if(!htotal || !vtotal) {
+               DPRINTK("XGIfb: Invalid 'var' information\n");
+               return -EINVAL;
+       }
+        printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
+                var->pixclock,htotal,vtotal);
+
+
+
+       if(var->pixclock && htotal && vtotal) {
+               drate = 1000000000 / var->pixclock;
+               hrate = (drate * 1000) / htotal;
+               xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+       } else {
+               xgi_video_info.refresh_rate = 60;
+       }
+
+       printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
+               var->xres,var->yres,var->bits_per_pixel,xgi_video_info.refresh_rate);
+
+       old_mode = xgifb_mode_idx;
+       xgifb_mode_idx = 0;
+
+       while( (XGIbios_mode[xgifb_mode_idx].mode_no != 0) &&
+              (XGIbios_mode[xgifb_mode_idx].xres <= var->xres) ) {
+               if( (XGIbios_mode[xgifb_mode_idx].xres == var->xres) &&
+                   (XGIbios_mode[xgifb_mode_idx].yres == var->yres) &&
+                   (XGIbios_mode[xgifb_mode_idx].bpp == var->bits_per_pixel)) {
+                       XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
+                       found_mode = 1;
+                       break;
+               }
+               xgifb_mode_idx++;
+       }
+
+       if(found_mode)
+               xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
+       else
+               xgifb_mode_idx = -1;
+
+               if(xgifb_mode_idx < 0) {
+               printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
+                      var->yres, var->bits_per_pixel);
+               xgifb_mode_idx = old_mode;
+               return -EINVAL;
+       }
+
+       if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
+               XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
+               xgi_video_info.refresh_rate = 60;
+       }
+
+       if(isactive) {
+
+
+               XGIfb_pre_setmode();
+               if(XGISetModeNew( &XGIhw_ext, XGIfb_mode_no) == 0) {
+                       printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
+                       return -EINVAL;
+               }
+       info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel)>>6);
+
+       outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
+
+               outXGIIDXREG(XGICR,0x13,(info->fix.line_length & 0x00ff));
+               outXGIIDXREG(XGISR,0x0E,(info->fix.line_length & 0xff00)>>8);
+
+               XGIfb_post_setmode();
+
+               DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n",
+                       XGIbios_mode[xgifb_mode_idx].xres,
+                       XGIbios_mode[xgifb_mode_idx].yres,
+                       XGIbios_mode[xgifb_mode_idx].bpp,
+                       xgi_video_info.refresh_rate);
+
+               xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
+               xgi_video_info.video_vwidth = info->var.xres_virtual;
+               xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
+               xgi_video_info.video_vheight = info->var.yres_virtual;
+               xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
+               xgi_video_info.org_x = xgi_video_info.org_y = 0;
+               xgi_video_info.video_linelength = info->var.xres_virtual * (xgi_video_info.video_bpp >> 3);
+               xgi_video_info.accel = 0;
+               if(XGIfb_accel) {
+                  xgi_video_info.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
+               }
+               switch(xgi_video_info.video_bpp)
+               {
+               case 8:
+                       xgi_video_info.DstColor = 0x0000;
+                       xgi_video_info.XGI310_AccelDepth = 0x00000000;
+                           xgi_video_info.video_cmap_len = 256;
+#if defined(__powerpc__)
+                inXGIIDXREG (XGICR, 0x4D, cr_data);
+                outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
+#endif
+                break;
+               case 16:
+               xgi_video_info.DstColor = 0x8000;
+               xgi_video_info.XGI310_AccelDepth = 0x00010000;
+#if defined(__powerpc__)
+                inXGIIDXREG (XGICR, 0x4D, cr_data);
+                outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
+#endif
+                           xgi_video_info.video_cmap_len = 16;
+               break;
+               case 32:
+               xgi_video_info.DstColor = 0xC000;
+                       xgi_video_info.XGI310_AccelDepth = 0x00020000;
+                           xgi_video_info.video_cmap_len = 16;
+#if defined(__powerpc__)
+                inXGIIDXREG (XGICR, 0x4D, cr_data);
+                outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
+#endif
+               break;
+                   default:
+                           xgi_video_info.video_cmap_len = 16;
+                       printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
+                           xgi_video_info.accel = 0;
+                           break;
+       }
+       }
+       XGIfb_bpp_to_var(var); /*update ARGB info*/
+       DEBUGPRN("End of do_set_var");
+
+       dumpVGAReg();
+       return 0;
+}
+
+#ifdef XGIFB_PAN
+static int XGIfb_pan_var(struct fb_var_screeninfo *var)
+{
+       unsigned int base;
+
+//     printk("Inside pan_var");
+
+       if (var->xoffset > (var->xres_virtual - var->xres)) {
+//             printk( "Pan: xo: %d xv %d xr %d\n",
+//                     var->xoffset, var->xres_virtual, var->xres);
+               return -EINVAL;
+       }
+       if(var->yoffset > (var->yres_virtual - var->yres)) {
+//             printk( "Pan: yo: %d yv %d yr %d\n",
+//                     var->yoffset, var->yres_virtual, var->yres);
+               return -EINVAL;
+       }
+        base = var->yoffset * var->xres_virtual + var->xoffset;
+
+        /* calculate base bpp dep. */
+        switch(var->bits_per_pixel) {
+        case 16:
+               base >>= 1;
+               break;
+       case 32:
+               break;
+       case 8:
+        default:
+               base >>= 2;
+               break;
+        }
+
+       outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
+
+        outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
+       outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
+       outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
+        outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
+       setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
+
+        if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
+               orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
+               outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
+               outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
+               outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
+               setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
+        }
+//     printk("End of pan_var");
+       return 0;
+}
+#endif
+
+
+void XGI_dispinfo(struct ap_data *rec)
+{
+       rec->minfo.bpp    = xgi_video_info.video_bpp;
+       rec->minfo.xres   = xgi_video_info.video_width;
+       rec->minfo.yres   = xgi_video_info.video_height;
+       rec->minfo.v_xres = xgi_video_info.video_vwidth;
+       rec->minfo.v_yres = xgi_video_info.video_vheight;
+       rec->minfo.org_x  = xgi_video_info.org_x;
+       rec->minfo.org_y  = xgi_video_info.org_y;
+       rec->minfo.vrate  = xgi_video_info.refresh_rate;
+       rec->iobase       = xgi_video_info.vga_base - 0x30;
+       rec->mem_size     = xgi_video_info.video_size;
+       rec->disp_state   = xgi_video_info.disp_state;
+       rec->version      = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
+       rec->hasVB        = xgi_video_info.hasVB;
+       rec->TV_type      = xgi_video_info.TV_type;
+       rec->TV_plug      = xgi_video_info.TV_plug;
+       rec->chip         = xgi_video_info.chip;
+}
+
+
+
+
+static int XGIfb_open(struct fb_info *info, int user)
+{
+    return 0;
+}
+
+static int XGIfb_release(struct fb_info *info, int user)
+{
+    return 0;
+}
+
+static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
+{
+       int rc = 16;
+
+       switch(var->bits_per_pixel) {
+       case 8:
+               rc = 256;
+               break;
+       case 16:
+               rc = 16;
+               break;
+       case 32:
+               rc = 16;
+               break;
+       }
+       return rc;
+}
+
+static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+                           unsigned transp, struct fb_info *info)
+{
+       if (regno >= XGIfb_get_cmap_len(&info->var))
+               return 1;
+
+       switch (info->var.bits_per_pixel) {
+       case 8:
+               outXGIREG(XGIDACA, regno);
+               outXGIREG(XGIDACD, (red >> 10));
+               outXGIREG(XGIDACD, (green >> 10));
+               outXGIREG(XGIDACD, (blue >> 10));
+               if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+                       outXGIREG(XGIDAC2A, regno);
+                       outXGIREG(XGIDAC2D, (red >> 8));
+                       outXGIREG(XGIDAC2D, (green >> 8));
+                       outXGIREG(XGIDAC2D, (blue >> 8));
+               }
+               break;
+       case 16:
+               ((u32 *)(info->pseudo_palette))[regno] =
+                   ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+               break;
+       case 32:
+               red >>= 8;
+               green >>= 8;
+               blue >>= 8;
+               ((u32 *) (info->pseudo_palette))[regno] =
+                       (red << 16) | (green << 8) | (blue);
+               break;
+       }
+       return 0;
+}
+
+static int XGIfb_set_par(struct fb_info *info)
+{
+       int err;
+
+//     printk("XGIfb: inside set_par\n");
+        if((err = XGIfb_do_set_var(&info->var, 1, info)))
+               return err;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+       XGIfb_get_fix(&info->fix, info->currcon, info);
+#else
+       XGIfb_get_fix(&info->fix, -1, info);
+#endif
+//     printk("XGIfb:end of set_par\n");
+       return 0;
+}
+
+static int XGIfb_check_var(struct fb_var_screeninfo *var,
+                           struct fb_info *info)
+{
+       unsigned int htotal =
+               var->left_margin + var->xres + var->right_margin +
+               var->hsync_len;
+       unsigned int vtotal = 0;
+       unsigned int drate = 0, hrate = 0;
+       int found_mode = 0;
+       int refresh_rate, search_idx;
+
+       DEBUGPRN("Inside check_var");
+
+       if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
+               vtotal = var->upper_margin + var->yres + var->lower_margin +
+                        var->vsync_len;
+               vtotal <<= 1;
+       } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+               vtotal = var->upper_margin + var->yres + var->lower_margin +
+                        var->vsync_len;
+               vtotal <<= 2;
+       } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+               vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
+                        var->vsync_len;
+       } else  vtotal = var->upper_margin + var->yres + var->lower_margin +
+                        var->vsync_len;
+
+       if(!(htotal) || !(vtotal)) {
+               XGIFAIL("XGIfb: no valid timing data");
+       }
+
+
+        if(var->pixclock && htotal && vtotal) {
+                drate = 1000000000 / var->pixclock;
+                hrate = (drate * 1000) / htotal;
+                xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+       printk(KERN_DEBUG \
+               "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \
+               "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
+               __func__,var->pixclock, htotal, vtotal,
+               __func__, drate, hrate, xgi_video_info.refresh_rate);
+        } else {
+                xgi_video_info.refresh_rate = 60;
+        }
+
+/*
+       if((var->pixclock) && (htotal)) {
+          drate = 1E12 / var->pixclock;
+          hrate = drate / htotal;
+          refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
+       } else refresh_rate = 60;
+*/
+       /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
+       if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;
+
+       search_idx = 0;
+       while((XGIbios_mode[search_idx].mode_no != 0) &&
+              (XGIbios_mode[search_idx].xres <= var->xres) ) {
+           if((XGIbios_mode[search_idx].xres == var->xres) &&
+              (XGIbios_mode[search_idx].yres == var->yres) &&
+                   (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
+                       if(XGIfb_validate_mode(search_idx) > 0) {
+                   found_mode = 1;
+                   break;
+               }
+           }
+               search_idx++;
+       }
+
+       if(!found_mode) {
+
+               printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
+                       var->xres, var->yres, var->bits_per_pixel);
+
+                search_idx = 0;
+               while(XGIbios_mode[search_idx].mode_no != 0) {
+
+                  if( (var->xres <= XGIbios_mode[search_idx].xres) &&
+                      (var->yres <= XGIbios_mode[search_idx].yres) &&
+                      (var->bits_per_pixel == XGIbios_mode[search_idx].bpp) ) {
+                         if(XGIfb_validate_mode(search_idx) > 0) {
+                            found_mode = 1;
+                            break;
+                         }
+                  }
+                  search_idx++;
+               }
+               if(found_mode) {
+                       var->xres = XGIbios_mode[search_idx].xres;
+                       var->yres = XGIbios_mode[search_idx].yres;
+                       printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
+                               var->xres, var->yres, var->bits_per_pixel);
+
+               } else {
+                       printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
+                               var->xres, var->yres, var->bits_per_pixel);
+                       return -EINVAL;
+               }
+       }
+
+       /* TW: TODO: Check the refresh rate */
+
+       /* Adapt RGB settings */
+       XGIfb_bpp_to_var(var);
+
+       /* Sanity check for offsets */
+       if (var->xoffset < 0)
+               var->xoffset = 0;
+       if (var->yoffset < 0)
+               var->yoffset = 0;
+
+
+       if(!XGIfb_ypan) {
+               if(var->xres != var->xres_virtual)
+                        var->xres_virtual = var->xres;
+               if(var->yres != var->yres_virtual)
+                       var->yres_virtual = var->yres;
+       }/* else {
+          // TW: Now patch yres_virtual if we use panning
+          // May I do this?
+          var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3));
+           if(var->yres_virtual <= var->yres) {
+               // TW: Paranoia check
+               var->yres_virtual = var->yres;
+           }
+       }*/
+
+       /* Truncate offsets to maximum if too high */
+       if (var->xoffset > var->xres_virtual - var->xres)
+               var->xoffset = var->xres_virtual - var->xres - 1;
+
+       if (var->yoffset > var->yres_virtual - var->yres)
+               var->yoffset = var->yres_virtual - var->yres - 1;
+
+       /* Set everything else to 0 */
+       var->red.msb_right =
+           var->green.msb_right =
+           var->blue.msb_right =
+           var->transp.offset = var->transp.length = var->transp.msb_right = 0;
+
+       DEBUGPRN("end of check_var");
+       return 0;
+}
+
+#ifdef XGIFB_PAN
+static int XGIfb_pan_display( struct fb_var_screeninfo *var,
+                                struct fb_info* info)
+{
+       int err;
+
+//     printk("\nInside pan_display:");
+
+       if (var->xoffset > (var->xres_virtual - var->xres))
+               return -EINVAL;
+       if (var->yoffset > (var->yres_virtual - var->yres))
+               return -EINVAL;
+
+       if (var->vmode & FB_VMODE_YWRAP) {
+               if (var->yoffset < 0
+                   || var->yoffset >= info->var.yres_virtual
+                   || var->xoffset) return -EINVAL;
+       } else {
+               if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+                   var->yoffset + info->var.yres > info->var.yres_virtual)
+                       return -EINVAL;
+       }
+
+       if((err = XGIfb_pan_var(var)) < 0) return err;
+
+       info->var.xoffset = var->xoffset;
+       info->var.yoffset = var->yoffset;
+       if (var->vmode & FB_VMODE_YWRAP)
+               info->var.vmode |= FB_VMODE_YWRAP;
+       else
+               info->var.vmode &= ~FB_VMODE_YWRAP;
+
+//     printk(" End of pan_display");
+       return 0;
+}
+#endif
+
+#if 0
+static int XGIfb_mmap(struct fb_info *info, struct file *file,
+                     struct vm_area_struct *vma)
+{
+       unsigned long start;
+       unsigned long off;
+       u32 len, mmio_off;
+
+       DEBUGPRN("inside mmap");
+       if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;
+
+       off = vma->vm_pgoff << PAGE_SHIFT;
+
+       start = (unsigned long) xgi_video_info.video_base;
+       len = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.video_size);
+       start &= PAGE_MASK;
+#if 0
+       if (off >= len) {
+               off -= len;
+#endif
+       /* By Jake Page: Treat mmap request with offset beyond heapstart
+        *               as request for mapping the mmio area
+        */
+       #if 1
+       mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.heapstart);
+       if(off >= mmio_off) {
+               off -= mmio_off;
+               if(info->var.accel_flags) return -EINVAL;
+
+               start = (unsigned long) xgi_video_info.mmio_base;
+               len = PAGE_ALIGN((start & ~PAGE_MASK) + XGIfb_mmio_size);
+       }
+       start &= PAGE_MASK;
+       #endif
+       if((vma->vm_end - vma->vm_start + off) > len)   return -EINVAL;
+
+       off += start;
+       vma->vm_pgoff = off >> PAGE_SHIFT;
+       vma->vm_flags |= VM_IO;   /* by Jake Page; is that really needed? */
+
+#if defined(__i386__) || defined(__x86_64__)
+       if (boot_cpu_data.x86 > 3)
+               pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+#endif
+       if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start,
+                               vma->vm_page_prot))
+               return -EAGAIN;
+
+        DEBUGPRN("end of mmap");
+       return 0;
+}
+#endif
+static int XGIfb_blank(int blank, struct fb_info *info)
+{
+       u8 reg;
+
+       inXGIIDXREG(XGICR, 0x17, reg);
+
+       if(blank > 0)
+               reg &= 0x7f;
+       else
+               reg |= 0x80;
+
+        outXGIIDXREG(XGICR, 0x17, reg);
+       outXGIIDXREG(XGISR, 0x00, 0x01);    /* Synchronous Reset */
+       outXGIIDXREG(XGISR, 0x00, 0x03);    /* End Reset */
+        return(0);
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
+                           unsigned long arg)
+#else
+static int XGIfb_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, unsigned long arg,
+                      struct fb_info *info)
+#endif
+
+{
+       DEBUGPRN("inside ioctl");
+       switch (cmd) {
+          case FBIO_ALLOC:
+               if (!capable(CAP_SYS_RAWIO))
+                       return -EPERM;
+               XGI_malloc((struct XGI_memreq *) arg);
+               break;
+          case FBIO_FREE:
+               if (!capable(CAP_SYS_RAWIO))
+                       return -EPERM;
+               XGI_free(*(unsigned long *) arg);
+               break;
+          case FBIOGET_HWCINFO:
+               {
+                       unsigned long *hwc_offset = (unsigned long *) arg;
+
+                       if (XGIfb_caps & HW_CURSOR_CAP)
+                               *hwc_offset = XGIfb_hwcursor_vbase -
+                                   (unsigned long) xgi_video_info.video_vbase;
+                       else
+                               *hwc_offset = 0;
+
+                       break;
+               }
+          case FBIOPUT_MODEINFO:
+               {
+                       struct mode_info *x = (struct mode_info *)arg;
+
+                       xgi_video_info.video_bpp        = x->bpp;
+                       xgi_video_info.video_width      = x->xres;
+                       xgi_video_info.video_height     = x->yres;
+                       xgi_video_info.video_vwidth     = x->v_xres;
+                       xgi_video_info.video_vheight    = x->v_yres;
+                       xgi_video_info.org_x            = x->org_x;
+                       xgi_video_info.org_y            = x->org_y;
+                       xgi_video_info.refresh_rate     = x->vrate;
+                       xgi_video_info.video_linelength = xgi_video_info.video_vwidth * (xgi_video_info.video_bpp >> 3);
+                       switch(xgi_video_info.video_bpp) {
+                       case 8:
+                               xgi_video_info.DstColor = 0x0000;
+                               xgi_video_info.XGI310_AccelDepth = 0x00000000;
+                               xgi_video_info.video_cmap_len = 256;
+                               break;
+                       case 16:
+                               xgi_video_info.DstColor = 0x8000;
+                               xgi_video_info.XGI310_AccelDepth = 0x00010000;
+                               xgi_video_info.video_cmap_len = 16;
+                               break;
+                       case 32:
+                               xgi_video_info.DstColor = 0xC000;
+                               xgi_video_info.XGI310_AccelDepth = 0x00020000;
+                               xgi_video_info.video_cmap_len = 16;
+                               break;
+                       default:
+                               xgi_video_info.video_cmap_len = 16;
+                               printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
+                               xgi_video_info.accel = 0;
+                               break;
+                       }
+
+                       break;
+               }
+          case FBIOGET_DISPINFO:
+               XGI_dispinfo((struct ap_data *)arg);
+               break;
+          case XGIFB_GET_INFO:  /* TW: New for communication with X driver */
+               {
+                       XGIfb_info *x = (XGIfb_info *)arg;
+
+                       //x->XGIfb_id = XGIFB_ID;
+                       x->XGIfb_version = VER_MAJOR;
+                       x->XGIfb_revision = VER_MINOR;
+                       x->XGIfb_patchlevel = VER_LEVEL;
+                       x->chip_id = xgi_video_info.chip_id;
+                       x->memory = xgi_video_info.video_size / 1024;
+                       x->heapstart = xgi_video_info.heapstart / 1024;
+                       x->fbvidmode = XGIfb_mode_no;
+                       x->XGIfb_caps = XGIfb_caps;
+                       x->XGIfb_tqlen = 512; /* yet unused */
+                       x->XGIfb_pcibus = xgi_video_info.pcibus;
+                       x->XGIfb_pcislot = xgi_video_info.pcislot;
+                       x->XGIfb_pcifunc = xgi_video_info.pcifunc;
+                       x->XGIfb_lcdpdc = XGIfb_detectedpdc;
+                       x->XGIfb_lcda = XGIfb_detectedlcda;
+                       break;
+               }
+          case XGIFB_GET_VBRSTATUS:
+               {
+                       unsigned long *vbrstatus = (unsigned long *) arg;
+                       if(XGIfb_CheckVBRetrace()) *vbrstatus = 1;
+                       else                       *vbrstatus = 0;
+               }
+          default:
+               return -EINVAL;
+       }
+       DEBUGPRN("end of ioctl");
+       return 0;
+
+}
+
+
+
+/* ----------- FBDev related routines for all series ---------- */
+
+static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+                        struct fb_info *info)
+{
+       DEBUGPRN("inside get_fix");
+       memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+       strcpy(fix->id, myid);
+
+       fix->smem_start = xgi_video_info.video_base;
+
+       fix->smem_len = xgi_video_info.video_size;
+
+
+/*        if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
+           if (xgi_video_info.video_size > 0x1000000) {
+               fix->smem_len = 0xD00000;
+           } else if (xgi_video_info.video_size > 0x800000)
+               fix->smem_len = 0x800000;
+           else
+               fix->smem_len = 0x400000;
+        } else
+               fix->smem_len = XGIfb_mem * 1024;
+*/
+       fix->type        = video_type;
+       fix->type_aux    = 0;
+       if(xgi_video_info.video_bpp == 8)
+               fix->visual = FB_VISUAL_PSEUDOCOLOR;
+       else
+               fix->visual = FB_VISUAL_DIRECTCOLOR;
+       fix->xpanstep    = 0;
+#ifdef XGIFB_PAN
+        if(XGIfb_ypan)          fix->ypanstep = 1;
+#endif
+       fix->ywrapstep   = 0;
+       fix->line_length = xgi_video_info.video_linelength;
+       fix->mmio_start  = xgi_video_info.mmio_base;
+       fix->mmio_len    = XGIfb_mmio_size;
+    if(xgi_video_info.chip >= XG40)
+          fix->accel    = FB_ACCEL_XGI_XABRE;
+       else
+          fix->accel    = FB_ACCEL_XGI_GLAMOUR_2;
+
+
+       DEBUGPRN("end of get_fix");
+       return 0;
+}
+
+
+static struct fb_ops XGIfb_ops = {
+       .owner        = THIS_MODULE,
+       .fb_open      = XGIfb_open,
+       .fb_release   = XGIfb_release,
+       .fb_check_var = XGIfb_check_var,
+       .fb_set_par   = XGIfb_set_par,
+       .fb_setcolreg = XGIfb_setcolreg,
+#ifdef XGIFB_PAN
+        .fb_pan_display = XGIfb_pan_display,
+#endif
+        .fb_blank     = XGIfb_blank,
+       .fb_fillrect  = fbcon_XGI_fillrect,
+       .fb_copyarea  = fbcon_XGI_copyarea,
+       .fb_imageblit = cfb_imageblit,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+       .fb_cursor    = soft_cursor,
+#endif
+       .fb_sync      = fbcon_XGI_sync,
+       .fb_ioctl     = XGIfb_ioctl,
+//     .fb_mmap      = XGIfb_mmap,
+};
+
+/* ---------------- Chip generation dependent routines ---------------- */
+
+
+/* for XGI 315/550/650/740/330 */
+
+static int XGIfb_get_dram_size(void)
+{
+
+       u8  ChannelNum,tmp;
+       u8  reg = 0;
+
+       /* xorg driver sets 32MB * 1 channel */
+       if (xgi_video_info.chip == XG27)
+               outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
+
+               inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
+               switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
+                  case XGI_DRAM_SIZE_1MB:
+                       xgi_video_info.video_size = 0x100000;
+                       break;
+                  case XGI_DRAM_SIZE_2MB:
+                       xgi_video_info.video_size = 0x200000;
+                       break;
+                  case XGI_DRAM_SIZE_4MB:
+                       xgi_video_info.video_size = 0x400000;
+                       break;
+                  case XGI_DRAM_SIZE_8MB:
+                       xgi_video_info.video_size = 0x800000;
+                       break;
+                  case XGI_DRAM_SIZE_16MB:
+                       xgi_video_info.video_size = 0x1000000;
+                       break;
+                  case XGI_DRAM_SIZE_32MB:
+                       xgi_video_info.video_size = 0x2000000;
+                       break;
+                  case XGI_DRAM_SIZE_64MB:
+                       xgi_video_info.video_size = 0x4000000;
+                       break;
+                  case XGI_DRAM_SIZE_128MB:
+                       xgi_video_info.video_size = 0x8000000;
+                       break;
+                  case XGI_DRAM_SIZE_256MB:
+                       xgi_video_info.video_size = 0x10000000;
+                       break;
+                  default:
+                       return -1;
+               }
+
+               tmp = (reg & 0x0c) >> 2;
+               switch(xgi_video_info.chip)
+               {
+                   case XG20:
+                    case XG21:
+                   case XG27:
+                       ChannelNum = 1;
+                       break;
+
+                   case XG42:
+                       if(reg & 0x04)
+                           ChannelNum = 2;
+                       else
+                           ChannelNum = 1;
+                       break;
+
+                   case XG45:
+                       if(tmp == 1)
+                    ChannelNum = 2;
+                else
+                if(tmp == 2)
+                    ChannelNum = 3;
+                else
+                if(tmp == 3)
+                    ChannelNum = 4;
+                else
+                    ChannelNum = 1;
+                       break;
+
+                   case XG40:
+                   default:
+                if(tmp == 2)
+                    ChannelNum = 2;
+                else
+                if(tmp == 3)
+                    ChannelNum = 3;
+                else
+                    ChannelNum = 1;
+                       break;
+               }
+
+
+               xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
+               //PLiad fixed for benchmarking and fb set
+               //xgi_video_info.video_size = 0x200000;//1024x768x16
+               //xgi_video_info.video_size = 0x1000000;//benchmark
+
+               printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg,xgi_video_info.video_size ,ChannelNum );
+               return 0;
+
+}
+
+static void XGIfb_detect_VB(void)
+{
+       u8 cr32, temp=0;
+
+       xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
+
+        switch(xgi_video_info.hasVB) {
+         case HASVB_LVDS_CHRONTEL:
+         case HASVB_CHRONTEL:
+            break;
+         case HASVB_301:
+         case HASVB_302:
+//          XGI_Sense30x(); //Yi-Lin TV Sense?
+            break;
+       }
+
+       inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
+
+       if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
+               XGIfb_crt1off = 0;
+       else {
+               if (cr32 & 0x5F)
+                       XGIfb_crt1off = 1;
+               else
+                       XGIfb_crt1off = 0;
+       }
+
+       if (XGIfb_crt2type != -1)
+               /* TW: Override with option */
+               xgi_video_info.disp_state = XGIfb_crt2type;
+       else if (cr32 & XGI_VB_TV)
+               xgi_video_info.disp_state = DISPTYPE_TV;
+       else if (cr32 & XGI_VB_LCD)
+               xgi_video_info.disp_state = DISPTYPE_LCD;
+       else if (cr32 & XGI_VB_CRT2)
+               xgi_video_info.disp_state = DISPTYPE_CRT2;
+       else
+               xgi_video_info.disp_state = 0;
+
+       if(XGIfb_tvplug != -1)
+               /* PR/TW: Override with option */
+               xgi_video_info.TV_plug = XGIfb_tvplug;
+       else if (cr32 & XGI_VB_HIVISION) {
+               xgi_video_info.TV_type = TVMODE_HIVISION;
+               xgi_video_info.TV_plug = TVPLUG_SVIDEO;
+       }
+       else if (cr32 & XGI_VB_SVIDEO)
+               xgi_video_info.TV_plug = TVPLUG_SVIDEO;
+       else if (cr32 & XGI_VB_COMPOSITE)
+               xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
+       else if (cr32 & XGI_VB_SCART)
+               xgi_video_info.TV_plug = TVPLUG_SCART;
+
+       if(xgi_video_info.TV_type == 0) {
+           /* TW: PAL/NTSC changed for 650 */
+           if((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip >= XGI_330)) {
+
+                inXGIIDXREG(XGICR, 0x38, temp);
+               if(temp & 0x10)
+                       xgi_video_info.TV_type = TVMODE_PAL;
+               else
+                       xgi_video_info.TV_type = TVMODE_NTSC;
+
+           } else {
+
+               inXGIIDXREG(XGICR, 0x79, temp);
+               if(temp & 0x20)
+                       xgi_video_info.TV_type = TVMODE_PAL;
+               else
+                       xgi_video_info.TV_type = TVMODE_NTSC;
+           }
+       }
+
+       /* TW: Copy forceCRT1 option to CRT1off if option is given */
+       if (XGIfb_forcecrt1 != -1) {
+               if (XGIfb_forcecrt1) XGIfb_crt1off = 0;
+               else                 XGIfb_crt1off = 1;
+       }
+}
+
+static void XGIfb_get_VB_type(void)
+{
+       u8 reg;
+
+       if (!XGIfb_has_VB()) {
+               inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
+               switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
+                  case XGI310_EXTERNAL_CHIP_LVDS:
+                       xgi_video_info.hasVB = HASVB_LVDS;
+                       break;
+                  case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
+                       xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
+                       break;
+                  default:
+                       break;
+               }
+       }
+}
+
+
+static int XGIfb_has_VB(void)
+{
+       u8 vb_chipid;
+
+       inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
+       switch (vb_chipid) {
+          case 0x01:
+               xgi_video_info.hasVB = HASVB_301;
+               break;
+          case 0x02:
+               xgi_video_info.hasVB = HASVB_302;
+               break;
+          default:
+               xgi_video_info.hasVB = HASVB_NONE;
+               return FALSE;
+       }
+       return TRUE;
+}
+
+
+
+/* ------------------ Sensing routines ------------------ */
+
+/* TW: Determine and detect attached devices on XGI30x */
+int
+XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
+{
+    int temp,i;
+
+    outXGIIDXREG(XGIPART4,0x11,tempbl);
+    temp = tempbh | tempcl;
+    setXGIIDXREG(XGIPART4,0x10,0xe0,temp);
+    for(i=0; i<10; i++) XGI_LongWait(&XGI_Pr);
+    tempch &= 0x7f;
+    inXGIIDXREG(XGIPART4,0x03,temp);
+    temp ^= 0x0e;
+    temp &= tempch;
+    return(temp);
+}
+
+void
+XGI_Sense30x(void)
+{
+  u8 backupP4_0d;
+  u8 testsvhs_tempbl, testsvhs_tempbh;
+  u8 testsvhs_tempcl, testsvhs_tempch;
+  u8 testcvbs_tempbl, testcvbs_tempbh;
+  u8 testcvbs_tempcl, testcvbs_tempch;
+  u8 testvga2_tempbl, testvga2_tempbh;
+  u8 testvga2_tempcl, testvga2_tempch;
+  int myflag, result;
+
+  inXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
+  outXGIIDXREG(XGIPART4,0x0d,(backupP4_0d | 0x04));
+
+
+
+       testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
+        testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
+       testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
+       if((XGIhw_ext.ujVBChipID != VB_CHIP_301) &&
+          (XGIhw_ext.ujVBChipID != VB_CHIP_302)) {
+             testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
+             testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
+             testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
+             if(XGIhw_ext.ujVBChipID == VB_CHIP_301LV ||
+                XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
+                testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
+                testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
+                testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
+             }
+       }
+       if(XGIhw_ext.ujVBChipID != VB_CHIP_301LV &&
+          XGIhw_ext.ujVBChipID != VB_CHIP_302LV) {
+          inXGIIDXREG(XGIPART4,0x01,myflag);
+          if(myflag & 0x04) {
+             testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
+             testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
+             testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
+          }
+       }
+       if((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
+          (XGIhw_ext.ujVBChipID == VB_CHIP_302LV) ) {
+          testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
+          testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
+          testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
+          testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
+       } else {
+          testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
+          testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
+          testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
+       }
+
+
+    if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
+        result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
+                            testvga2_tempcl, testvga2_tempch);
+       if(result) {
+               printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
+               orXGIIDXREG(XGICR, 0x32, 0x10);
+       }
+    }
+
+    result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh,
+                        testsvhs_tempcl, testsvhs_tempch);
+    if(result) {
+        printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
+        /* TW: So we can be sure that there IS a SVHS output */
+       xgi_video_info.TV_plug = TVPLUG_SVIDEO;
+       orXGIIDXREG(XGICR, 0x32, 0x02);
+    }
+
+    if(!result) {
+        result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
+                           testcvbs_tempcl, testcvbs_tempch);
+       if(result) {
+           printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
+           /* TW: So we can be sure that there IS a CVBS output */
+           xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
+           orXGIIDXREG(XGICR, 0x32, 0x01);
+       }
+    }
+    XGIDoSense(0, 0, 0, 0);
+
+    outXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
+}
+
+
+
+/* ------------------------ Heap routines -------------------------- */
+
+static int XGIfb_heap_init(void)
+{
+       XGI_OH *poh;
+       u8 temp=0;
+
+       int            agp_enabled = 1;
+       u32            agp_size;
+       unsigned long *cmdq_baseport = 0;
+       unsigned long *read_port = 0;
+       unsigned long *write_port = 0;
+       XGI_CMDTYPE    cmd_type;
+#ifndef AGPOFF
+       struct agp_kern_info  *agp_info;
+       struct agp_memory     *agp;
+       u32            agp_phys;
+#endif
+
+/* TW: The heap start is either set manually using the "mem" parameter, or
+ *     defaults as follows:
+ *     -) If more than 16MB videoRAM available, let our heap start at 12MB.
+ *     -) If more than  8MB videoRAM available, let our heap start at  8MB.
+ *     -) If 4MB or less is available, let it start at 4MB.
+ *     This is for avoiding a clash with X driver which uses the beginning
+ *     of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
+ *     in XF86Config-4.
+ *     The heap start can also be specified by parameter "mem" when starting the XGIfb
+ *     driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
+ */
+     if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
+        if (xgi_video_info.video_size > 0x1000000) {
+               xgi_video_info.heapstart = 0xD00000;
+       } else if (xgi_video_info.video_size > 0x800000) {
+               xgi_video_info.heapstart = 0x800000;
+       } else {
+               xgi_video_info.heapstart = 0x400000;
+       }
+     } else {
+           xgi_video_info.heapstart = XGIfb_mem * 1024;
+     }
+     XGIfb_heap_start =
+              (unsigned long) (xgi_video_info.video_vbase + xgi_video_info.heapstart);
+     printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
+                                       (int)(xgi_video_info.heapstart / 1024));
+
+     XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase + xgi_video_info.video_size;
+     XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
+
+
+
+        /* TW: Now initialize the 310 series' command queue mode.
+        * On 310/325, there are three queue modes available which
+        * are chosen by setting bits 7:5 in SR26:
+        * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
+        *    track of the queue, the FIFO, command parsing and so
+        *    on. This is the one comparable to the 300 series.
+        * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
+        *    have to do queue management himself. Register 0x85c4 will
+        *    hold the location of the next free queue slot, 0x85c8
+        *    is the "queue read pointer" whose way of working is
+        *    unknown to me. Anyway, this mode would require a
+        *    translation of the MMIO commands to some kind of
+        *    accelerator assembly and writing these commands
+        *    to the memory location pointed to by 0x85c4.
+        *    We will not use this, as nobody knows how this
+        *    "assembly" works, and as it would require a complete
+        *    re-write of the accelerator code.
+        * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
+        *    queue in AGP memory space.
+        *
+        * SR26 bit 4 is called "Bypass H/W queue".
+        * SR26 bit 1 is called "Enable Command Queue Auto Correction"
+        * SR26 bit 0 resets the queue
+        * Size of queue memory is encoded in bits 3:2 like this:
+        *    00  (0x00)  512K
+        *    01  (0x04)  1M
+        *    10  (0x08)  2M
+        *    11  (0x0C)  4M
+        * The queue location is to be written to 0x85C0.
+        *
+         */
+       cmdq_baseport = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_PHYBASE);
+       write_port    = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_WRITEPORT);
+       read_port     = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_READPORT);
+
+       DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
+
+       agp_size  = COMMAND_QUEUE_AREA_SIZE;
+
+#ifndef AGPOFF
+       if (XGIfb_queuemode == AGP_CMD_QUEUE) {
+               agp_info = vmalloc(sizeof(*agp_info));
+               memset((void*)agp_info, 0x00, sizeof(*agp_info));
+               agp_copy_info(agp_info);
+
+               agp_backend_acquire();
+
+               agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
+                                         AGP_NORMAL_MEMORY);
+               if (agp == NULL) {
+                       DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
+                       agp_enabled = 0;
+               } else {
+                       if (agp_bind_memory(agp, agp->pg_start) != 0) {
+                               DPRINTK("XGIfb: AGP: Failed to bind memory\n");
+                               /* TODO: Free AGP memory here */
+                               agp_enabled = 0;
+                       } else {
+                               agp_enable(0);
+                       }
+               }
+       }
+#else
+       agp_enabled = 0;
+#endif
+
+       /* TW: Now select the queue mode */
+
+       if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
+               cmd_type = AGP_CMD_QUEUE;
+               printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
+/*     } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)  */
+        } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
+               cmd_type = VM_CMD_QUEUE;
+               printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
+       } else {
+               printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
+               cmd_type = MMIO_CMD;
+       }
+
+       switch (agp_size) {
+          case 0x80000:
+               temp = XGI_CMD_QUEUE_SIZE_512k;
+               break;
+          case 0x100000:
+               temp = XGI_CMD_QUEUE_SIZE_1M;
+               break;
+          case 0x200000:
+               temp = XGI_CMD_QUEUE_SIZE_2M;
+               break;
+          case 0x400000:
+               temp = XGI_CMD_QUEUE_SIZE_4M;
+               break;
+       }
+
+       switch (cmd_type) {
+          case AGP_CMD_QUEUE:
+#ifndef AGPOFF
+               DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
+                       agp_info->aper_base, agp->physical, agp_size/1024);
+
+               agp_phys = agp_info->aper_base + agp->physical;
+
+               outXGIIDXREG(XGICR,  IND_XGI_AGP_IO_PAD, 0);
+               outXGIIDXREG(XGICR,  IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
+
+                outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+
+               outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
+
+               *write_port = *read_port;
+
+               temp |= XGI_AGP_CMDQUEUE_ENABLE;
+               outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
+
+               *cmdq_baseport = agp_phys;
+
+               XGIfb_caps |= AGP_CMD_QUEUE_CAP;
+#endif
+               break;
+
+          case VM_CMD_QUEUE:
+               XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+               XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
+
+               outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+
+               outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
+
+               *write_port = *read_port;
+
+               temp |= XGI_VRAM_CMDQUEUE_ENABLE;
+               outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
+
+               *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
+
+               XGIfb_caps |= VM_CMD_QUEUE_CAP;
+
+               DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
+                       *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
+               break;
+
+          default:  /* MMIO */
+
+//             printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__);
+               /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
+                * to IND_XGI_CMDQUEUE_SET. I doubt that this is
+                * enough. Reserve memory in any way.
+                */
+// FIXME               XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+// FIXME               XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
+// FIXME
+// FIXME               outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+// FIXME               outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
+// FIXME
+// FIXME               *write_port = *read_port;
+// FIXME
+// FIXME               /* TW: Set Auto_Correction bit */
+// FIXME               temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR);
+// FIXME               // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
+// FIXME
+// FIXME               *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
+// FIXME
+// FIXME               XGIfb_caps |= MMIO_CMD_QUEUE_CAP;
+// FIXME
+// FIXME               DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
+// FIXME                       *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
+               break;
+       }
+
+
+
+
+     /* TW: Now reserve memory for the HWCursor. It is always located at the very
+            top of the videoRAM, right below the TB memory area (if used). */
+     if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
+               XGIfb_heap_end -= XGIfb_hwcursor_size;
+               XGIfb_heap_size -= XGIfb_hwcursor_size;
+               XGIfb_hwcursor_vbase = XGIfb_heap_end;
+
+               XGIfb_caps |= HW_CURSOR_CAP;
+
+               DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
+                       XGIfb_heap_end, XGIfb_hwcursor_size/1024);
+     }
+
+     XGIfb_heap.poha_chain = NULL;
+     XGIfb_heap.poh_freelist = NULL;
+
+     poh = XGIfb_poh_new_node();
+
+     if(poh == NULL)  return 1;
+
+     poh->poh_next = &XGIfb_heap.oh_free;
+     poh->poh_prev = &XGIfb_heap.oh_free;
+     poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
+     poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
+
+     DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
+               (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
+               (unsigned int) poh->size / 1024);
+
+     DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
+               (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
+
+     XGIfb_heap.oh_free.poh_next = poh;
+     XGIfb_heap.oh_free.poh_prev = poh;
+     XGIfb_heap.oh_free.size = 0;
+     XGIfb_heap.max_freesize = poh->size;
+
+     XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
+     XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
+     XGIfb_heap.oh_used.size = SENTINEL;
+
+     return 0;
+}
+
+static XGI_OH *XGIfb_poh_new_node(void)
+{
+       int           i;
+       unsigned long cOhs;
+       XGI_OHALLOC   *poha;
+       XGI_OH        *poh;
+
+       if (XGIfb_heap.poh_freelist == NULL) {
+               poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
+               if(!poha) return NULL;
+
+               poha->poha_next = XGIfb_heap.poha_chain;
+               XGIfb_heap.poha_chain = poha;
+
+               cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH) + 1;
+
+               poh = &poha->aoh[0];
+               for (i = cOhs - 1; i != 0; i--) {
+                       poh->poh_next = poh + 1;
+                       poh = poh + 1;
+               }
+
+               poh->poh_next = NULL;
+               XGIfb_heap.poh_freelist = &poha->aoh[0];
+       }
+
+       poh = XGIfb_heap.poh_freelist;
+       XGIfb_heap.poh_freelist = poh->poh_next;
+
+       return (poh);
+}
+
+static XGI_OH *XGIfb_poh_allocate(unsigned long size)
+{
+       XGI_OH *pohThis;
+       XGI_OH *pohRoot;
+       int     bAllocated = 0;
+
+       if (size > XGIfb_heap.max_freesize) {
+               DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
+                       (unsigned int) size / 1024);
+               return (NULL);
+       }
+
+       pohThis = XGIfb_heap.oh_free.poh_next;
+
+       while (pohThis != &XGIfb_heap.oh_free) {
+               if (size <= pohThis->size) {
+                       bAllocated = 1;
+                       break;
+               }
+               pohThis = pohThis->poh_next;
+       }
+
+       if (!bAllocated) {
+               DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
+                       (unsigned int) size / 1024);
+               return (NULL);
+       }
+
+       if (size == pohThis->size) {
+               pohRoot = pohThis;
+               XGIfb_delete_node(pohThis);
+       } else {
+               pohRoot = XGIfb_poh_new_node();
+
+               if (pohRoot == NULL) {
+                       return (NULL);
+               }
+
+               pohRoot->offset = pohThis->offset;
+               pohRoot->size = size;
+
+               pohThis->offset += size;
+               pohThis->size -= size;
+       }
+
+       XGIfb_heap.max_freesize -= size;
+
+       pohThis = &XGIfb_heap.oh_used;
+       XGIfb_insert_node(pohThis, pohRoot);
+
+       return (pohRoot);
+}
+
+static void XGIfb_delete_node(XGI_OH *poh)
+{
+       XGI_OH *poh_prev;
+       XGI_OH *poh_next;
+
+       poh_prev = poh->poh_prev;
+       poh_next = poh->poh_next;
+
+       poh_prev->poh_next = poh_next;
+       poh_next->poh_prev = poh_prev;
+
+}
+
+static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
+{
+       XGI_OH *pohTemp;
+
+       pohTemp = pohList->poh_next;
+
+       pohList->poh_next = poh;
+       pohTemp->poh_prev = poh;
+
+       poh->poh_prev = pohList;
+       poh->poh_next = pohTemp;
+}
+
+static XGI_OH *XGIfb_poh_free(unsigned long base)
+{
+       XGI_OH *pohThis;
+       XGI_OH *poh_freed;
+       XGI_OH *poh_prev;
+       XGI_OH *poh_next;
+       unsigned long ulUpper;
+       unsigned long ulLower;
+       int foundNode = 0;
+
+       poh_freed = XGIfb_heap.oh_used.poh_next;
+
+       while(poh_freed != &XGIfb_heap.oh_used) {
+               if(poh_freed->offset == base) {
+                       foundNode = 1;
+                       break;
+               }
+
+               poh_freed = poh_freed->poh_next;
+       }
+
+       if (!foundNode)  return (NULL);
+
+       XGIfb_heap.max_freesize += poh_freed->size;
+
+       poh_prev = poh_next = NULL;
+       ulUpper = poh_freed->offset + poh_freed->size;
+       ulLower = poh_freed->offset;
+
+       pohThis = XGIfb_heap.oh_free.poh_next;
+
+       while (pohThis != &XGIfb_heap.oh_free) {
+               if (pohThis->offset == ulUpper) {
+                       poh_next = pohThis;
+               }
+                       else if ((pohThis->offset + pohThis->size) ==
+                                ulLower) {
+                       poh_prev = pohThis;
+               }
+               pohThis = pohThis->poh_next;
+       }
+
+       XGIfb_delete_node(poh_freed);
+
+       if (poh_prev && poh_next) {
+               poh_prev->size += (poh_freed->size + poh_next->size);
+               XGIfb_delete_node(poh_next);
+               XGIfb_free_node(poh_freed);
+               XGIfb_free_node(poh_next);
+               return (poh_prev);
+       }
+
+       if (poh_prev) {
+               poh_prev->size += poh_freed->size;
+               XGIfb_free_node(poh_freed);
+               return (poh_prev);
+       }
+
+       if (poh_next) {
+               poh_next->size += poh_freed->size;
+               poh_next->offset = poh_freed->offset;
+               XGIfb_free_node(poh_freed);
+               return (poh_next);
+       }
+
+       XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
+
+       return (poh_freed);
+}
+
+static void XGIfb_free_node(XGI_OH *poh)
+{
+       if(poh == NULL) return;
+
+       poh->poh_next = XGIfb_heap.poh_freelist;
+       XGIfb_heap.poh_freelist = poh;
+
+}
+
+void XGI_malloc(struct XGI_memreq *req)
+{
+       XGI_OH *poh;
+
+       poh = XGIfb_poh_allocate(req->size);
+
+       if(poh == NULL) {
+               req->offset = 0;
+               req->size = 0;
+               DPRINTK("XGIfb: Video RAM allocation failed\n");
+       } else {
+               DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
+                       (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
+
+               req->offset = poh->offset;
+               req->size = poh->size;
+       }
+
+}
+
+void XGI_free(unsigned long base)
+{
+       XGI_OH *poh;
+
+       poh = XGIfb_poh_free(base);
+
+       if(poh == NULL) {
+               DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
+                       (unsigned int) base);
+       }
+}
+
+/* --------------------- SetMode routines ------------------------- */
+
+static void XGIfb_pre_setmode(void)
+{
+       u8 cr30 = 0, cr31 = 0;
+
+       inXGIIDXREG(XGICR, 0x31, cr31);
+       cr31 &= ~0x60;
+
+       switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+          case DISPTYPE_CRT2:
+               cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
+               cr31 |= XGI_DRIVER_MODE;
+               break;
+          case DISPTYPE_LCD:
+               cr30  = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
+               cr31 |= XGI_DRIVER_MODE;
+               break;
+          case DISPTYPE_TV:
+               if (xgi_video_info.TV_type == TVMODE_HIVISION)
+                       cr30 = (XGI_VB_OUTPUT_HIVISION | XGI_SIMULTANEOUS_VIEW_ENABLE);
+               else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
+                       cr30 = (XGI_VB_OUTPUT_SVIDEO | XGI_SIMULTANEOUS_VIEW_ENABLE);
+               else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
+                       cr30 = (XGI_VB_OUTPUT_COMPOSITE | XGI_SIMULTANEOUS_VIEW_ENABLE);
+               else if (xgi_video_info.TV_plug == TVPLUG_SCART)
+                       cr30 = (XGI_VB_OUTPUT_SCART | XGI_SIMULTANEOUS_VIEW_ENABLE);
+               cr31 |= XGI_DRIVER_MODE;
+
+               if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
+                       cr31 |= 0x01;
+                else
+                        cr31 &= ~0x01;
+               break;
+          default:     /* disable CRT2 */
+               cr30 = 0x00;
+               cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
+       }
+
+       outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
+       outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
+        outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
+
+       if(xgi_video_info.accel) XGIfb_syncaccel();
+
+
+}
+
+static void XGIfb_post_setmode(void)
+{
+       u8 reg;
+       BOOLEAN doit = TRUE;
+#if 0  /* TW: Wrong: Is not in MMIO space, but in RAM */
+       /* Backup mode number to MMIO space */
+       if(xgi_video_info.mmio_vbase) {
+         *(volatile u8 *)(((u8*)xgi_video_info.mmio_vbase) + 0x449) = (unsigned char)XGIfb_mode_no;
+       }
+#endif
+/*     outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
+       outXGIIDXREG(XGICR,0x13,0x00);
+       setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
+*test**/
+       if (xgi_video_info.video_bpp == 8) {
+               /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
+               if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
+                       doit = FALSE;
+               }
+               /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
+               if  (xgi_video_info.disp_state & DISPTYPE_LCD)  {
+                       doit = FALSE;
+               }
+       }
+
+       /* TW: We can't switch off CRT1 if bridge is in slave mode */
+       if(xgi_video_info.hasVB != HASVB_NONE) {
+               inXGIIDXREG(XGIPART1, 0x00, reg);
+
+
+               if((reg & 0x50) == 0x10) {
+                       doit = FALSE;
+               }
+
+       } else XGIfb_crt1off = 0;
+
+       inXGIIDXREG(XGICR, 0x17, reg);
+       if((XGIfb_crt1off) && (doit))
+               reg &= ~0x80;
+       else
+               reg |= 0x80;
+       outXGIIDXREG(XGICR, 0x17, reg);
+
+        andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
+
+       if((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB == HASVB_301)) {
+
+          inXGIIDXREG(XGIPART4, 0x01, reg);
+
+          if(reg < 0xB0) {             /* Set filter for XGI301 */
+
+               switch (xgi_video_info.video_width) {
+                  case 320:
+                       filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
+                       break;
+                  case 640:
+                       filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
+                       break;
+                  case 720:
+                       filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
+                       break;
+                  case 800:
+                       filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
+                       break;
+                  default:
+                       filter = -1;
+                       break;
+               }
+
+               orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
+
+               if(xgi_video_info.TV_type == TVMODE_NTSC) {
+
+                       andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
+
+                       if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
+
+                               andXGIIDXREG(XGIPART2, 0x30, 0xdf);
+
+                       } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
+
+                               orXGIIDXREG(XGIPART2, 0x30, 0x20);
+
+                               switch (xgi_video_info.video_width) {
+                               case 640:
+                                       outXGIIDXREG(XGIPART2, 0x35, 0xEB);
+                                       outXGIIDXREG(XGIPART2, 0x36, 0x04);
+                                       outXGIIDXREG(XGIPART2, 0x37, 0x25);
+                                       outXGIIDXREG(XGIPART2, 0x38, 0x18);
+                                       break;
+                               case 720:
+                                       outXGIIDXREG(XGIPART2, 0x35, 0xEE);
+                                       outXGIIDXREG(XGIPART2, 0x36, 0x0C);
+                                       outXGIIDXREG(XGIPART2, 0x37, 0x22);
+                                       outXGIIDXREG(XGIPART2, 0x38, 0x08);
+                                       break;
+                               case 800:
+                                       outXGIIDXREG(XGIPART2, 0x35, 0xEB);
+                                       outXGIIDXREG(XGIPART2, 0x36, 0x15);
+                                       outXGIIDXREG(XGIPART2, 0x37, 0x25);
+                                       outXGIIDXREG(XGIPART2, 0x38, 0xF6);
+                                       break;
+                               }
+                       }
+
+               } else if(xgi_video_info.TV_type == TVMODE_PAL) {
+
+                       andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
+
+                       if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
+
+                               andXGIIDXREG(XGIPART2, 0x30, 0xDF);
+
+                       } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
+
+                               orXGIIDXREG(XGIPART2, 0x30, 0x20);
+
+                               switch (xgi_video_info.video_width) {
+                               case 640:
+                                       outXGIIDXREG(XGIPART2, 0x35, 0xF1);
+                                       outXGIIDXREG(XGIPART2, 0x36, 0xF7);
+                                       outXGIIDXREG(XGIPART2, 0x37, 0x1F);
+                                       outXGIIDXREG(XGIPART2, 0x38, 0x32);
+                                       break;
+                               case 720:
+                                       outXGIIDXREG(XGIPART2, 0x35, 0xF3);
+                                       outXGIIDXREG(XGIPART2, 0x36, 0x00);
+                                       outXGIIDXREG(XGIPART2, 0x37, 0x1D);
+                                       outXGIIDXREG(XGIPART2, 0x38, 0x20);
+                                       break;
+                               case 800:
+                                       outXGIIDXREG(XGIPART2, 0x35, 0xFC);
+                                       outXGIIDXREG(XGIPART2, 0x36, 0xFB);
+                                       outXGIIDXREG(XGIPART2, 0x37, 0x14);
+                                       outXGIIDXREG(XGIPART2, 0x38, 0x2A);
+                                       break;
+                               }
+                       }
+               }
+
+               if ((filter >= 0) && (filter <=7)) {
+                       DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
+                               XGI_TV_filter[filter_tb].filter[filter][0],
+                               XGI_TV_filter[filter_tb].filter[filter][1],
+                               XGI_TV_filter[filter_tb].filter[filter][2],
+                               XGI_TV_filter[filter_tb].filter[filter][3]
+                       );
+                       outXGIIDXREG(XGIPART2, 0x35, (XGI_TV_filter[filter_tb].filter[filter][0]));
+                       outXGIIDXREG(XGIPART2, 0x36, (XGI_TV_filter[filter_tb].filter[filter][1]));
+                       outXGIIDXREG(XGIPART2, 0x37, (XGI_TV_filter[filter_tb].filter[filter][2]));
+                       outXGIIDXREG(XGIPART2, 0x38, (XGI_TV_filter[filter_tb].filter[filter][3]));
+               }
+
+            }
+
+       }
+
+}
+
+#ifndef MODULE
+XGIINITSTATIC int __init XGIfb_setup(char *options)
+{
+       char *this_opt;
+
+
+
+       xgi_video_info.refresh_rate = 0;
+
+        printk(KERN_INFO "XGIfb: Options %s\n", options);
+
+       if (!options || !*options)
+               return 0;
+
+       while((this_opt = strsep(&options, ",")) != NULL) {
+
+               if (!*this_opt) continue;
+
+               if (!strncmp(this_opt, "mode:", 5)) {
+                       XGIfb_search_mode(this_opt + 5);
+               } else if (!strncmp(this_opt, "vesa:", 5)) {
+                       XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
+               } else if (!strncmp(this_opt, "mode:", 5)) {
+                       XGIfb_search_mode(this_opt + 5);
+               } else if (!strncmp(this_opt, "vesa:", 5)) {
+                       XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
+               } else if (!strncmp(this_opt, "vrate:", 6)) {
+                       xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
+               } else if (!strncmp(this_opt, "rate:", 5)) {
+                       xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
+               } else if (!strncmp(this_opt, "off", 3)) {
+                       XGIfb_off = 1;
+               } else if (!strncmp(this_opt, "crt1off", 7)) {
+                       XGIfb_crt1off = 1;
+               } else if (!strncmp(this_opt, "filter:", 7)) {
+                       filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
+               } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
+                       XGIfb_search_crt2type(this_opt + 14);
+               } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
+                       XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
+                } else if (!strncmp(this_opt, "tvmode:",7)) {
+                       XGIfb_search_tvstd(this_opt + 7);
+                } else if (!strncmp(this_opt, "tvstandard:",11)) {
+                       XGIfb_search_tvstd(this_opt + 7);
+                } else if (!strncmp(this_opt, "mem:",4)) {
+                       XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
+                } else if (!strncmp(this_opt, "dstn", 4)) {
+                       enable_dstn = 1;
+                       /* TW: DSTN overrules forcecrt2type */
+                       XGIfb_crt2type = DISPTYPE_LCD;
+               } else if (!strncmp(this_opt, "queuemode:", 10)) {
+                       XGIfb_search_queuemode(this_opt + 10);
+               } else if (!strncmp(this_opt, "pdc:", 4)) {
+                       XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
+                       if(XGIfb_pdc & ~0x3c) {
+                          printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
+                          XGIfb_pdc = 0;
+                       }
+               } else if (!strncmp(this_opt, "noaccel", 7)) {
+                       XGIfb_accel = 0;
+               } else if (!strncmp(this_opt, "noypan", 6)) {
+                       XGIfb_ypan = 0;
+               } else if (!strncmp(this_opt, "userom:", 7)) {
+                       XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
+//             } else if (!strncmp(this_opt, "useoem:", 7)) {
+//                     XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
+               } else {
+                       XGIfb_search_mode(this_opt);
+//                     printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt);
+               }
+
+               /* TW: Acceleration only with MMIO mode */
+               if((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
+                       XGIfb_ypan = 0;
+                       XGIfb_accel = 0;
+               }
+               /* TW: Panning only with acceleration */
+               if(XGIfb_accel == 0) XGIfb_ypan = 0;
+
+       }
+       printk("\nxgifb: outa xgifb_setup 3450");
+       return 0;
+}
+#endif
+
+static unsigned char VBIOS_BUF[65535];
+
+unsigned char* attempt_map_rom(struct pci_dev *dev,void *copy_address)
+{
+    u32 rom_size      = 0;
+    u32 rom_address   = 0;
+    int j;
+
+    /*  Get the size of the expansion rom */
+    pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
+    pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
+    if ((rom_size & 0x01) == 0)
+    {
+               printk("No ROM\n");
+               return NULL;
+    }
+
+    rom_size &= 0xFFFFF800;
+    rom_size = (~rom_size)+1;
+
+    rom_address = pci_resource_start(dev, 0);
+    if (rom_address == 0 || rom_address == 0xFFFFFFF0)
+    {
+               printk("No suitable rom address found\n"); return NULL;
+    }
+
+    printk("ROM Size is %dK, Address is %x\n", rom_size/1024, rom_address);
+
+    /*  Map ROM */
+    pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE);
+
+    /* memcpy(copy_address, rom_address, rom_size); */
+    {
+               unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
+
+               unsigned char *from = (unsigned char *)virt_addr;
+               unsigned char *to = (unsigned char *)copy_address;
+               for (j=0; j<65536 /*rom_size*/; j++) *to++ = *from++;
+       }
+
+       pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+
+    printk("Copy is done\n");
+
+       return copy_address;
+}
+
+int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       u16 reg16;
+       u8  reg, reg1;
+        u8 CR48,CR38;
+       if (XGIfb_off)
+               return -ENXIO;
+
+       XGIfb_registered = 0;
+
+       memset(&XGIhw_ext, 0, sizeof(HW_DEVICE_EXTENSION));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
+         fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
+         if(!fb_info) return -ENOMEM;
+#else
+         XGI_fb_info = kmalloc( sizeof(struct fb_info), GFP_KERNEL);
+         if(!XGI_fb_info) return -ENOMEM;
+         memset(XGI_fb_info, 0,  sizeof(struct fb_info));
+#endif
+
+       xgi_video_info.chip_id = pdev->device;
+         pci_read_config_byte(pdev, PCI_REVISION_ID,&xgi_video_info.revision_id);
+         pci_read_config_word(pdev, PCI_COMMAND, &reg16);
+         XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
+         XGIvga_enabled = reg16 & 0x01;
+
+         xgi_video_info.pcibus = pdev->bus->number;
+         xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
+         xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
+         xgi_video_info.subsysvendor = pdev->subsystem_vendor;
+         xgi_video_info.subsysdevice = pdev->subsystem_device;
+
+         xgi_video_info.video_base = pci_resource_start(pdev, 0);
+         xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
+         XGIfb_mmio_size =  pci_resource_len(pdev, 1);
+         xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
+         XGIhw_ext.pjIOAddress = (PUCHAR)xgi_video_info.vga_base;
+         //XGI_Pr.RelIO  = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
+         printk("XGIfb: Relocate IO address: %lx [%08lx] \n", (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
+
+         if (pci_enable_device(pdev))
+                 return -EIO;
+
+    XGIRegInit(&XGI_Pr, (ULONG)XGIhw_ext.pjIOAddress);
+
+    outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
+    inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
+
+    if(reg1 != 0xa1) /*I/O error */
+    {
+         printk("\nXGIfb: I/O error!!!");
+         return  -EIO;
+    }
+
+       switch (xgi_video_info.chip_id) {
+          case PCI_DEVICE_ID_XG_20:
+               orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
+               inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
+               if (CR48&GPIOG_READ)
+                       xgi_video_info.chip = XG21;
+               else
+                       xgi_video_info.chip = XG20;
+               XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+               XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+               break;
+           case PCI_DEVICE_ID_XG_40:
+               xgi_video_info.chip = XG40;
+               XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+               XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+               break;
+           case PCI_DEVICE_ID_XG_41:
+               xgi_video_info.chip = XG41;
+               XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+               XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+               break;
+           case PCI_DEVICE_ID_XG_42:
+               xgi_video_info.chip = XG42;
+               XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+               XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+               break;
+           case PCI_DEVICE_ID_XG_27:
+               xgi_video_info.chip = XG27;
+               XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+               XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+               break;
+           default:
+               return -ENODEV;
+       }
+
+       printk("XGIfb:chipid = %x\n",xgi_video_info.chip);
+        XGIhw_ext.jChipType = xgi_video_info.chip;
+
+               switch (xgi_video_info.chip) {
+                  case XG40:
+                  case XG41:
+                  case XG42:
+                  case XG45:
+                  case XG20:
+                  case XG21:
+                   case XG27:
+                   XGIhw_ext.bIntegratedMMEnabled = TRUE;
+                       break;
+
+                  default:
+                       break;
+               }
+
+
+         XGIhw_ext.pDevice = NULL;
+         if ((xgi_video_info.chip == XG21) || (XGIfb_userom))
+         {
+             XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
+
+             if(XGIhw_ext.pjVirtualRomBase)
+                       printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext.pjVirtualRomBase);
+               else
+                       printk(KERN_INFO "XGIfb: Video ROM not found\n");
+    } else {
+               XGIhw_ext.pjVirtualRomBase = NULL;
+               printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
+    }
+         XGIhw_ext.pjCustomizedROMImage = NULL;
+         XGIhw_ext.bSkipDramSizing = 0;
+         XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
+//     XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space;
+         strcpy(XGIhw_ext.szVBIOSVer, "0.84");
+
+
+    XGIhw_ext.pSR = vmalloc(sizeof(XGI_DSReg) * SR_BUFFER_SIZE);
+         if (XGIhw_ext.pSR == NULL)
+         {
+                   printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
+                   return -ENODEV;
+         }
+         XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
+
+         XGIhw_ext.pCR = vmalloc(sizeof(XGI_DSReg) * CR_BUFFER_SIZE);
+         if (XGIhw_ext.pCR == NULL)
+         {
+             vfree(XGIhw_ext.pSR);
+                   printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
+                   return -ENODEV;
+         }
+         XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
+
+
+
+
+       if (!XGIvga_enabled)
+       {
+                       /* Mapping Max FB Size for 315 Init */
+           XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
+           if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
+           {
+#ifdef LINUXBIOS
+               printk("XGIfb: XGIInit() ...");
+               /* XGIInitNewt for LINUXBIOS only */
+               if(XGIInitNew(&XGIhw_ext))
+               {
+                       printk("OK\n");
+               }
+               else
+               {
+                   printk("Fail\n");
+               }
+#endif
+
+               outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
+
+
+           }
+       }
+#ifdef LINUXBIOS
+       else
+       {
+           XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
+           if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
+           {
+
+               outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
+
+               // yilin Because no VBIOS DRAM Sizing, Dram size will error.
+               // Set SR13 ,14 temporarily for UDtech
+               outXGIIDXREG(XGISR, 0x13, 0x45);
+               outXGIIDXREG(XGISR, 0x14, 0x51);
+
+
+           }
+       }
+#endif
+       if (XGIfb_get_dram_size())
+       {
+           vfree(XGIhw_ext.pSR);
+           vfree(XGIhw_ext.pCR);
+           printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
+           return -ENODEV;
+       }
+
+
+
+         if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
+         {
+              /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
+        orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
+         /* Enable 2D accelerator engine */
+        orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
+    }
+
+         XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
+
+         if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB"))
+         {         printk("unable request memory size %x",xgi_video_info.video_size);
+                   printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
+                   printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
+                   vfree(XGIhw_ext.pSR);
+                   vfree(XGIhw_ext.pCR);
+                   return -ENODEV;
+         }
+
+         if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO"))
+         {
+                   printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
+                   release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
+                   vfree(XGIhw_ext.pSR);
+                   vfree(XGIhw_ext.pCR);
+                   return -ENODEV;
+         }
+
+         xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
+               ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
+         xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
+
+         printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
+             xgi_video_info.video_base, xgi_video_info.video_vbase,xgi_video_info.video_size / 1024);
+
+         printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
+             xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,XGIfb_mmio_size / 1024);
+          printk("XGIfb: XGIInitNew() ...");
+         if(XGIInitNew(&XGIhw_ext))
+         {
+                 printk("OK\n");
+         }
+         else
+         {
+               printk("Fail\n");
+         }
+
+         if(XGIfb_heap_init())
+         {
+                   printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
+         }
+
+
+         xgi_video_info.mtrr = (unsigned int) 0;
+
+         if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
+         {
+                 xgi_video_info.hasVB = HASVB_NONE;
+        if((xgi_video_info.chip == XG20)||(xgi_video_info.chip == XG27))
+             xgi_video_info.hasVB = HASVB_NONE;
+        else if(xgi_video_info.chip == XG21) {
+            inXGIIDXREG(XGICR,0x38,CR38);
+            if ((CR38&0xE0) == 0xC0) {
+                   xgi_video_info.disp_state = DISPTYPE_LCD;
+                   if (!XGIfb_GetXG21LVDSData()) {
+                           int m;
+                           for (m=0; m < sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct); m++) {
+                                   if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
+                                       (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
+                                               XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ;
+                                   }
+                           }
+                   }
+            }
+            else if ((CR38&0xE0) == 0x60)
+               xgi_video_info.hasVB = HASVB_CHRONTEL ;
+            else
+               xgi_video_info.hasVB = HASVB_NONE;
+       }
+        else
+                   XGIfb_get_VB_type();
+
+                   XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
+
+                   XGIhw_ext.ulExternalChip = 0;
+
+               switch (xgi_video_info.hasVB) {
+               case HASVB_301:
+                       inXGIIDXREG(XGIPART4, 0x01, reg);
+                       if (reg >= 0xE0) {
+                               XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
+                               printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
+                       } else if (reg >= 0xD0) {
+                               XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
+                               printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg);
+                       }
+                       /* else if (reg >= 0xB0) {
+                               XGIhw_ext.ujVBChipID = VB_CHIP_301B;
+                               inXGIIDXREG(XGIPART4,0x23,reg1);
+                              printk("XGIfb: XGI301B bridge detected\n");
+                       }*/
+                       else {
+                               XGIhw_ext.ujVBChipID = VB_CHIP_301;
+                               printk("XGIfb: XGI301 bridge detected\n");
+                       }
+                       break;
+               case HASVB_302:
+                       inXGIIDXREG(XGIPART4, 0x01, reg);
+                       if (reg >= 0xE0) {
+                               XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
+                               printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
+                       } else if (reg >= 0xD0) {
+                               XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
+                               printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
+                       } else if (reg >= 0xB0) {
+                               inXGIIDXREG(XGIPART4,0x23,reg1);
+
+                               XGIhw_ext.ujVBChipID = VB_CHIP_302B;
+
+                       } else {
+                               XGIhw_ext.ujVBChipID = VB_CHIP_302;
+                               printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
+                       }
+                       break;
+               case HASVB_LVDS:
+                       XGIhw_ext.ulExternalChip = 0x1;
+                       printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
+                       break;
+               case HASVB_TRUMPION:
+                       XGIhw_ext.ulExternalChip = 0x2;
+                       printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
+                       break;
+               case HASVB_CHRONTEL:
+                       XGIhw_ext.ulExternalChip = 0x4;
+                       printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
+                       break;
+               case HASVB_LVDS_CHRONTEL:
+                       XGIhw_ext.ulExternalChip = 0x5;
+                       printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
+                       break;
+               default:
+                       printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
+                       break;
+               }
+
+               if (xgi_video_info.hasVB != HASVB_NONE) {
+                   XGIfb_detect_VB();
+    }
+
+               if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+                       if (XGIfb_crt1off)
+                               xgi_video_info.disp_state |= DISPMODE_SINGLE;
+                       else
+                               xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
+               } else {
+                       xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
+               }
+
+               if (xgi_video_info.disp_state & DISPTYPE_LCD) {
+                   if (!enable_dstn) {
+                       inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
+                           reg &= 0x0f;
+                           XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
+
+                   } else {
+                       // TW: FSTN/DSTN
+                       XGIhw_ext.ulCRT2LCDType = LCD_320x480;
+                   }
+               }
+
+               XGIfb_detectedpdc = 0;
+
+               XGIfb_detectedlcda = 0xff;
+#ifndef LINUXBIOS
+
+                /* TW: Try to find about LCDA */
+
+        if((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
+              (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
+              (XGIhw_ext.ujVBChipID == VB_CHIP_302LV))
+           {
+              int tmp;
+              inXGIIDXREG(XGICR,0x34,tmp);
+              if(tmp <= 0x13)
+              {
+                 // Currently on LCDA? (Some BIOSes leave CR38)
+                 inXGIIDXREG(XGICR,0x38,tmp);
+                     if((tmp & 0x03) == 0x03)
+                     {
+//                       XGI_Pr.XGI_UseLCDA = TRUE;
+                     }else
+                     {
+                    //  Currently on LCDA? (Some newer BIOSes set D0 in CR35)
+                        inXGIIDXREG(XGICR,0x35,tmp);
+                        if(tmp & 0x01)
+                        {
+//                           XGI_Pr.XGI_UseLCDA = TRUE;
+                          }else
+                          {
+                              inXGIIDXREG(XGICR,0x30,tmp);
+                              if(tmp & 0x20)
+                              {
+                                  inXGIIDXREG(XGIPART1,0x13,tmp);
+                                      if(tmp & 0x04)
+                                      {
+//                                     XGI_Pr.XGI_UseLCDA = TRUE;
+                                      }
+                              }
+                          }
+                       }
+                }
+
+        }
+
+
+#endif
+
+               if (xgifb_mode_idx >= 0)
+                       xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
+
+               if (xgifb_mode_idx < 0) {
+                       switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+                          case DISPTYPE_LCD:
+                               xgifb_mode_idx = DEFAULT_LCDMODE;
+                               if (xgi_video_info.chip == XG21)
+                               {
+                                   xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
+                               }
+                               break;
+                          case DISPTYPE_TV:
+                               xgifb_mode_idx = DEFAULT_TVMODE;
+                               break;
+                          default:
+                               xgifb_mode_idx = DEFAULT_MODE;
+                               break;
+                       }
+               }
+
+               XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
+
+
+                if( xgi_video_info.refresh_rate == 0)
+                   xgi_video_info.refresh_rate = 60; /*yilin set default refresh rate */
+               if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0)
+                {
+                   XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
+                   xgi_video_info.refresh_rate = 60;
+               }
+
+               xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
+               xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
+               xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
+               xgi_video_info.org_x = xgi_video_info.org_y = 0;
+               xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
+               switch(xgi_video_info.video_bpp) {
+               case 8:
+                       xgi_video_info.DstColor = 0x0000;
+                       xgi_video_info.XGI310_AccelDepth = 0x00000000;
+                       xgi_video_info.video_cmap_len = 256;
+                       break;
+               case 16:
+                       xgi_video_info.DstColor = 0x8000;
+                       xgi_video_info.XGI310_AccelDepth = 0x00010000;
+                       xgi_video_info.video_cmap_len = 16;
+                       break;
+               case 32:
+                       xgi_video_info.DstColor = 0xC000;
+                       xgi_video_info.XGI310_AccelDepth = 0x00020000;
+                       xgi_video_info.video_cmap_len = 16;
+                       break;
+               default:
+                       xgi_video_info.video_cmap_len = 16;
+                       printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
+                       break;
+               }
+
+
+
+               printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
+                       xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
+                       xgi_video_info.refresh_rate);
+
+               default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
+               default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
+               default_var.bits_per_pixel = xgi_video_info.video_bpp;
+
+               XGIfb_bpp_to_var(&default_var);
+
+               default_var.pixclock = (u32) (1000000000 /
+                               XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
+                                               XGIfb_mode_no, XGIfb_rate_idx));
+
+               if(XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
+                        XGIfb_mode_no, XGIfb_rate_idx,
+                        &default_var.left_margin, &default_var.right_margin,
+                        &default_var.upper_margin, &default_var.lower_margin,
+                        &default_var.hsync_len, &default_var.vsync_len,
+                        &default_var.sync, &default_var.vmode)) {
+
+                  if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+                     default_var.yres <<= 1;
+                     default_var.yres_virtual <<= 1;
+                  } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+                     default_var.pixclock >>= 1;
+                     default_var.yres >>= 1;
+                     default_var.yres_virtual >>= 1;
+                  }
+
+               }
+
+
+#if 0
+#ifdef XGIFB_PAN
+               if(XGIfb_ypan) {
+                       default_var.yres_virtual =
+                               xgi_video_info.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
+                       if(default_var.yres_virtual <= default_var.yres) {
+                               default_var.yres_virtual = default_var.yres;
+                       }
+               }
+#endif
+#endif
+
+
+               xgi_video_info.accel = 0;
+               if(XGIfb_accel) {
+                  xgi_video_info.accel = -1;
+                  default_var.accel_flags |= FB_ACCELF_TEXT;
+                  XGIfb_initaccel();
+               }
+
+               fb_info->flags = FBINFO_FLAG_DEFAULT;
+               fb_info->var = default_var;
+               fb_info->fix = XGIfb_fix;
+               fb_info->par = &xgi_video_info;
+               fb_info->screen_base = xgi_video_info.video_vbase;
+               fb_info->fbops = &XGIfb_ops;
+               XGIfb_get_fix(&fb_info->fix, -1, fb_info);
+               fb_info->pseudo_palette = pseudo_palette;
+
+               fb_alloc_cmap(&fb_info->cmap, 256 , 0);
+
+
+#ifdef CONFIG_MTRR
+               xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
+                               (unsigned int) xgi_video_info.video_size,
+                               MTRR_TYPE_WRCOMB, 1);
+               if(xgi_video_info.mtrr) {
+                       printk(KERN_INFO "XGIfb: Added MTRRs\n");
+               }
+#endif
+
+               if(register_framebuffer(fb_info) < 0)
+    {
+                       return -EINVAL;
+    }
+
+               XGIfb_registered = 1;
+
+               printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%x)\n", XGIFB_GET_INFO);
+
+/*             printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
+                    XGIfb_accel ? "enabled" : "disabled",
+                    XGIfb_ypan  ? "ypan" : "redraw");
+*/
+               printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
+                       fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
+
+
+       }
+
+       dumpVGAReg();
+
+       return 0;
+}
+
+
+/*****************************************************/
+/*                PCI DEVICE HANDLING                */
+/*****************************************************/
+
+static void __devexit xgifb_remove(struct pci_dev *pdev)
+{
+       /* Unregister the framebuffer */
+//     if(xgi_video_info.registered) {
+               unregister_framebuffer(fb_info);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
+               framebuffer_release(fb_info);
+#else
+               kfree(fb_info);
+#endif
+//     }
+
+       pci_set_drvdata(pdev, NULL);
+
+};
+
+static struct pci_driver xgifb_driver = {
+       .name           = "xgifb",
+       .id_table       = xgifb_pci_table,
+       .probe          = xgifb_probe,
+       .remove         = __devexit_p(xgifb_remove)
+};
+
+XGIINITSTATIC int __init xgifb_init(void)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("xgifb", &option))
+               return -ENODEV;
+       XGIfb_setup(option);
+#endif
+#endif
+       return(pci_register_driver(&xgifb_driver));
+}
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+#ifndef MODULE
+module_init(xgifb_init);
+#endif
+#endif
+
+/*****************************************************/
+/*                      MODULE                       */
+/*****************************************************/
+
+#ifdef MODULE
+
+static char         *mode = NULL;
+static int          vesa = 0;
+static unsigned int rate = 0;
+static unsigned int crt1off = 1;
+static unsigned int mem = 0;
+static char         *forcecrt2type = NULL;
+static int          forcecrt1 = -1;
+static int          pdc = -1;
+static int          pdc1 = -1;
+static int          noaccel = -1;
+static int          noypan  = -1;
+static int         nomax = -1;
+static int          userom = -1;
+static int          useoem = -1;
+static char         *tvstandard = NULL;
+static int         nocrt2rate = 0;
+static int          scalelcd = -1;
+static char        *specialtiming = NULL;
+static int         lvdshl = -1;
+static int         tvxposoffset = 0, tvyposoffset = 0;
+#if !defined(__i386__) && !defined(__x86_64__)
+static int         resetcard = 0;
+static int         videoram = 0;
+#endif
+
+MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("XGITECH , Others");
+
+
+
+module_param(mem, int, 0);
+module_param(noaccel, int, 0);
+module_param(noypan, int, 0);
+module_param(nomax, int, 0);
+module_param(userom, int, 0);
+module_param(useoem, int, 0);
+module_param(mode, charp, 0);
+module_param(vesa, int, 0);
+module_param(rate, int, 0);
+module_param(forcecrt1, int, 0);
+module_param(forcecrt2type, charp, 0);
+module_param(scalelcd, int, 0);
+module_param(pdc, int, 0);
+module_param(pdc1, int, 0);
+module_param(specialtiming, charp, 0);
+module_param(lvdshl, int, 0);
+module_param(tvstandard, charp, 0);
+module_param(tvxposoffset, int, 0);
+module_param(tvyposoffset, int, 0);
+module_param(filter, int, 0);
+module_param(nocrt2rate, int, 0);
+#if !defined(__i386__) && !defined(__x86_64__)
+module_param(resetcard, int, 0);
+module_param(videoram, int, 0);
+#endif
+
+
+MODULE_PARM_DESC(mem,
+       "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
+         "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
+         "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
+         "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
+         "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
+         "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
+         "for XFree86 4.x/X.org 6.7 and later.\n");
+
+MODULE_PARM_DESC(noaccel,
+        "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
+         "(default: 0)\n");
+
+MODULE_PARM_DESC(noypan,
+        "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
+         "will be performed by redrawing the screen. (default: 0)\n");
+
+MODULE_PARM_DESC(nomax,
+        "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
+         "memory for the virtual screen in order to optimize scrolling performance. If\n"
+         "this is set to anything other than 0, xgifb will not do this and thereby \n"
+         "enable the user to positively specify a virtual Y size of the screen using\n"
+         "fbset. (default: 0)\n");
+
+
+
+MODULE_PARM_DESC(mode,
+       "\nSelects the desired default display mode in the format XxYxDepth,\n"
+         "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
+        "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
+        "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
+
+MODULE_PARM_DESC(vesa,
+       "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
+         "0x117 (default: 0x0103)\n");
+
+
+MODULE_PARM_DESC(rate,
+       "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
+         "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
+         "will be ignored (default: 60)\n");
+
+MODULE_PARM_DESC(forcecrt1,
+       "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
+         "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
+         "0=CRT1 OFF) (default: [autodetected])\n");
+
+MODULE_PARM_DESC(forcecrt2type,
+       "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
+         "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
+         "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
+         "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
+         "be used instead of TV to override the TV detection. Furthermore, on systems\n"
+         "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
+         "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
+         "depends on the very hardware in use. (default: [autodetected])\n");
+
+MODULE_PARM_DESC(scalelcd,
+       "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
+         "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
+         "show black bars around the image, TMDS panels will probably do the scaling\n"
+         "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
+
+MODULE_PARM_DESC(pdc,
+        "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
+         "should detect this correctly in most cases; however, sometimes this is not\n"
+         "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
+         "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
+         "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
+         "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
+
+MODULE_PARM_DESC(pdc1,
+        "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
+         "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
+         "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
+         "implemented yet.\n");
+
+MODULE_PARM_DESC(specialtiming,
+       "\nPlease refer to documentation for more information on this option.\n");
+
+MODULE_PARM_DESC(lvdshl,
+       "\nPlease refer to documentation for more information on this option.\n");
+
+MODULE_PARM_DESC(tvstandard,
+       "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
+         "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
+
+MODULE_PARM_DESC(tvxposoffset,
+       "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
+         "Default: 0\n");
+
+MODULE_PARM_DESC(tvyposoffset,
+       "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
+         "Default: 0\n");
+
+MODULE_PARM_DESC(filter,
+       "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
+         "(Possible values 0-7, default: [no filter])\n");
+
+MODULE_PARM_DESC(nocrt2rate,
+       "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
+         "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
+
+
+
+
+int __init xgifb_init_module(void)
+{
+        printk("\nXGIfb_init_module");
+       if(mode)
+               XGIfb_search_mode(mode);
+       else if (vesa != -1)
+               XGIfb_search_vesamode(vesa);
+
+        return(xgifb_init());
+}
+
+static void __exit xgifb_remove_module(void)
+{
+       pci_unregister_driver(&xgifb_driver);
+       printk(KERN_DEBUG "xgifb: Module unloaded\n");
+}
+
+module_init(xgifb_init_module);
+module_exit(xgifb_remove_module);
+
+#endif            /*  /MODULE  */
+
+EXPORT_SYMBOL(XGI_malloc);
+EXPORT_SYMBOL(XGI_free);
+
diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h
new file mode 100644 (file)
index 0000000..41bf163
--- /dev/null
@@ -0,0 +1,215 @@
+#ifndef _LINUX_XGIFB
+#define _LINUX_XGIFB
+#include <linux/spinlock.h>
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
+#define DISPTYPE_CRT1       0x00000008L
+#define DISPTYPE_CRT2       0x00000004L
+#define DISPTYPE_LCD        0x00000002L
+#define DISPTYPE_TV         0x00000001L
+#define DISPTYPE_DISP1      DISPTYPE_CRT1
+#define DISPTYPE_DISP2      (DISPTYPE_CRT2 | DISPTYPE_LCD | DISPTYPE_TV)
+#define DISPMODE_SINGLE            0x00000020L
+#define DISPMODE_MIRROR            0x00000010L
+#define DISPMODE_DUALVIEW   0x00000040L
+
+#define HASVB_NONE             0x00
+#define HASVB_301              0x01
+#define HASVB_LVDS             0x02
+#define HASVB_TRUMPION         0x04
+#define HASVB_LVDS_CHRONTEL    0x10
+#define HASVB_302              0x20
+#define HASVB_303              0x40
+#define HASVB_CHRONTEL         0x80
+
+#ifndef XGIFB_ID
+#define XGIFB_ID          0x53495346    /* Identify myself with 'XGIF' */
+#endif
+
+typedef enum _XGI_CHIP_TYPE {
+    XGI_VGALegacy = 0,
+    XGI_300,
+    XGI_630,
+    XGI_730,
+    XGI_540,
+    XGI_315H,
+    XGI_315,
+    XGI_315PRO,
+    XGI_550,
+    XGI_640,
+    XGI_740,
+    XGI_650,
+    XGI_650M,
+    XGI_330 = 16,
+    XGI_660,
+    XGI_661,
+    XGI_760,
+    XG40 = 32,
+    XG41,
+    XG42,
+    XG45,
+    XG20 = 48,
+    XG21,
+    XG27,
+    MAX_XGI_CHIP
+} XGI_CHIP_TYPE;
+
+typedef enum _TVTYPE {
+       TVMODE_NTSC = 0,
+       TVMODE_PAL,
+       TVMODE_HIVISION,
+       TVTYPE_PALM,    // vicki@030226
+       TVTYPE_PALN,    // vicki@030226
+       TVTYPE_NTSCJ,   // vicki@030226
+       TVMODE_TOTAL
+} XGI_TV_TYPE;
+
+
+typedef struct _XGIFB_INFO XGIfb_info;
+struct _XGIFB_INFO {
+
+unsigned long XGIfb_id;
+       int    chip_id;                 /* PCI ID of detected chip */
+       int    memory;                  /* video memory in KB which XGIfb manages */
+       int    heapstart;               /* heap start (= XGIfb "mem" argument) in KB */
+       unsigned char fbvidmode;        /* current XGIfb mode */
+
+       unsigned char XGIfb_version;
+       unsigned char XGIfb_revision;
+       unsigned char XGIfb_patchlevel;
+
+       unsigned char XGIfb_caps;       /* XGIfb capabilities */
+
+       int    XGIfb_tqlen;             /* turbo queue length (in KB) */
+
+       unsigned int XGIfb_pcibus;      /* The card's PCI ID */
+       unsigned int XGIfb_pcislot;
+       unsigned int XGIfb_pcifunc;
+
+       unsigned char XGIfb_lcdpdc;     /* PanelDelayCompensation */
+
+       unsigned char XGIfb_lcda;       /* Detected status of LCDA for low res/text modes */
+
+       char reserved[235];             /* for future use */
+};
+
+
+
+
+typedef enum _TVPLUGTYPE {     // vicki@030226
+//     TVPLUG_Legacy = 0,
+//     TVPLUG_COMPOSITE,
+//     TVPLUG_SVIDEO,
+//     TVPLUG_SCART,
+//     TVPLUG_TOTAL
+       TVPLUG_UNKNOWN = 0,
+       TVPLUG_COMPOSITE = 1,
+       TVPLUG_SVIDEO = 2,
+       TVPLUG_COMPOSITE_AND_SVIDEO = 3,
+       TVPLUG_SCART = 4,
+       TVPLUG_YPBPR_525i = 5,
+       TVPLUG_YPBPR_525P = 6,
+       TVPLUG_YPBPR_750P = 7,
+       TVPLUG_YPBPR_1080i = 8,
+       TVPLUG_TOTAL
+} XGI_TV_PLUG;
+
+
+struct mode_info {
+       int    bpp;
+       int    xres;
+       int    yres;
+       int    v_xres;
+       int    v_yres;
+       int    org_x;
+       int    org_y;
+       unsigned int  vrate;
+};
+
+struct ap_data {
+       struct mode_info minfo;
+       unsigned long iobase;
+       unsigned int  mem_size;
+       unsigned long disp_state;
+       XGI_CHIP_TYPE chip;
+       unsigned char hasVB;
+       XGI_TV_TYPE TV_type;
+       XGI_TV_PLUG TV_plug;
+       unsigned long version;
+       char reserved[256];
+};
+
+
+
+/*     If changing this, vgatypes.h must also be changed (for X driver)    */
+
+
+/*
+ * NOTE! The ioctl types used to be "size_t" by mistake, but were
+ * really meant to be __u32. Changed to "__u32" even though that
+ * changes the value on 64-bit architectures, because the value
+ * (with a 4-byte size) is also hardwired in vgatypes.h for user
+ * space exports. So "__u32" is actually more compatible, duh!
+ */
+#define XGIFB_GET_INFO         _IOR('n',0xF8,__u32)
+#define XGIFB_GET_VBRSTATUS    _IOR('n',0xF9,__u32)
+
+
+
+struct video_info{
+        int           chip_id;
+        unsigned int  video_size;
+        unsigned long video_base;
+        char  *       video_vbase;
+        unsigned long mmio_base;
+        char  *       mmio_vbase;
+        unsigned long vga_base;
+        unsigned long mtrr;
+        unsigned long heapstart;
+
+        int    video_bpp;
+        int    video_cmap_len;
+        int    video_width;
+        int    video_height;
+        int    video_vwidth;
+        int    video_vheight;
+        int    org_x;
+        int    org_y;
+        int    video_linelength;
+        unsigned int refresh_rate;
+
+        unsigned long disp_state;
+        unsigned char hasVB;
+        unsigned char TV_type;
+        unsigned char TV_plug;
+
+        XGI_CHIP_TYPE chip;
+        unsigned char revision_id;
+
+        unsigned short DstColor;
+        unsigned long  XGI310_AccelDepth;
+        unsigned long  CommandReg;
+
+        spinlock_t     lockaccel;
+
+        unsigned int   pcibus;
+        unsigned int   pcislot;
+        unsigned int   pcifunc;
+
+        int            accel;
+        unsigned short subsysvendor;
+        unsigned short subsysdevice;
+
+        char reserved[236];
+};
+
+
+extern struct video_info xgi_video_info;
+
+#ifdef __KERNEL__
+//extern void xgi_malloc(struct xgi_memreq *req);
+extern void xgi_free(unsigned long base);
+extern void xgi_dispinfo(struct ap_data *rec);
+#endif
+#endif
diff --git a/drivers/staging/xgifb/osdef.h b/drivers/staging/xgifb/osdef.h
new file mode 100644 (file)
index 0000000..4bc7d3a
--- /dev/null
@@ -0,0 +1,153 @@
+#ifndef _OSDEF_H_
+#define _OSDEF_H_
+
+/* #define WINCE_HEADER*/
+/*#define WIN2000*/
+/* #define TC */
+#define LINUX_KERNEL
+/* #define LINUX_XF86 */
+
+/**********************************************************************/
+#ifdef LINUX_KERNEL
+//#include <linux/config.h>
+#endif
+
+
+/**********************************************************************/
+#ifdef TC
+#endif
+#ifdef WIN2000
+#endif
+#ifdef WINCE_HEADER
+#endif
+#ifdef LINUX_XF86
+#define LINUX
+#endif
+#ifdef LINUX_KERNEL
+#define LINUX
+#endif
+
+/**********************************************************************/
+#ifdef TC
+#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
+#endif
+#ifdef WIN2000
+#define XGI_SetMemory(MemoryAddress,MemorySize,value) MemFill((PVOID) MemoryAddress,(ULONG) MemorySize,(UCHAR) value);
+#endif
+#ifdef WINCE_HEADER
+#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
+#endif
+#ifdef LINUX_XF86
+#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+#endif
+#ifdef LINUX_KERNEL
+#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+#endif
+/**********************************************************************/
+
+/**********************************************************************/
+
+#ifdef TC
+#define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
+#endif
+#ifdef WIN2000
+#define XGI_MemoryCopy(Destination,Soruce,Length)  /*VideoPortMoveMemory((PUCHAR)Destination , Soruce,length);*/
+#endif
+#ifdef WINCE_HEADER
+#define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
+#endif
+#ifdef LINUX_XF86
+#define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+#endif
+#ifdef LINUX_KERNEL
+#define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+#endif
+
+/**********************************************************************/
+
+#ifdef OutPortByte
+#undef OutPortByte
+#endif /* OutPortByte */
+
+#ifdef OutPortWord
+#undef OutPortWord
+#endif /* OutPortWord */
+
+#ifdef OutPortLong
+#undef OutPortLong
+#endif /* OutPortLong */
+
+#ifdef InPortByte
+#undef InPortByte
+#endif /* InPortByte */
+
+#ifdef InPortWord
+#undef InPortWord
+#endif /* InPortWord */
+
+#ifdef InPortLong
+#undef InPortLong
+#endif /* InPortLong */
+
+/**********************************************************************/
+/*  TC                                                                */
+/**********************************************************************/
+
+#ifdef TC
+#define OutPortByte(p,v) outp((unsigned short)(p),(unsigned char)(v))
+#define OutPortWord(p,v) outp((unsigned short)(p),(unsigned short)(v))
+#define OutPortLong(p,v) outp((unsigned short)(p),(unsigned long)(v))
+#define InPortByte(p)    inp((unsigned short)(p))
+#define InPortWord(p)    inp((unsigned short)(p))
+#define InPortLong(p)    ((inp((unsigned short)(p+2))<<16) | inp((unsigned short)(p)))
+#endif
+
+/**********************************************************************/
+/*  LINUX XF86                                                        */
+/**********************************************************************/
+
+#ifdef LINUX_XF86
+#define OutPortByte(p,v) outb((CARD16)(p),(CARD8)(v))
+#define OutPortWord(p,v) outw((CARD16)(p),(CARD16)(v))
+#define OutPortLong(p,v) outl((CARD16)(p),(CARD32)(v))
+#define InPortByte(p)    inb((CARD16)(p))
+#define InPortWord(p)    inw((CARD16)(p))
+#define InPortLong(p)    inl((CARD16)(p))
+#endif
+
+#ifdef LINUX_KERNEL
+#define OutPortByte(p,v) outb((u8)(v),(p))
+#define OutPortWord(p,v) outw((u16)(v),(p))
+#define OutPortLong(p,v) outl((u32)(v),(p))
+#define InPortByte(p)    inb(p)
+#define InPortWord(p)    inw(p)
+#define InPortLong(p)    inl(p)
+#endif
+
+/**********************************************************************/
+/*  WIN 2000                                                          */
+/**********************************************************************/
+
+#ifdef WIN2000
+#define OutPortByte(p,v) VideoPortWritePortUchar ((PUCHAR) (p), (UCHAR) (v))
+#define OutPortWord(p,v) VideoPortWritePortUshort((PUSHORT) (p), (USHORT) (v))
+#define OutPortLong(p,v) VideoPortWritePortUlong ((PULONG) (p), (ULONG) (v))
+#define InPortByte(p)    VideoPortReadPortUchar  ((PUCHAR) (p))
+#define InPortWord(p)    VideoPortReadPortUshort ((PUSHORT) (p))
+#define InPortLong(p)    VideoPortReadPortUlong  ((PULONG) (p))
+#endif
+
+
+/**********************************************************************/
+/*  WIN CE                                                          */
+/**********************************************************************/
+
+#ifdef WINCE_HEADER
+#define OutPortByte(p,v) WRITE_PORT_UCHAR ((PUCHAR) (p), (UCHAR) (v))
+#define OutPortWord(p,v) WRITE_PORT_USHORT((PUSHORT) (p), (USHORT) (v))
+#define OutPortLong(p,v) WRITE_PORT_ULONG ((PULONG) (p), (ULONG) (v))
+#define InPortByte(p)    READ_PORT_UCHAR  ((PUCHAR) (p))
+#define InPortWord(p)    READ_PORT_USHORT ((PUSHORT) (p))
+#define InPortLong(p)    READ_PORT_ULONG  ((PULONG) (p))
+#endif
+#endif // _OSDEF_H_
diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h
new file mode 100644 (file)
index 0000000..17a7ada
--- /dev/null
@@ -0,0 +1,1017 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/xgi/initdef.h,v 1.4 2000/12/02 01:16:17 dawes Exp $ */
+#ifndef _INITDEF_
+#define _INITDEF_
+
+#ifndef NewScratch
+#define NewScratch
+#endif
+/* shampoo */
+#ifdef LINUX_KERNEL
+#define SEQ_ADDRESS_PORT         0x0014
+#define SEQ_DATA_PORT            0x0015
+#define MISC_OUTPUT_REG_READ_PORT 0x001C
+#define MISC_OUTPUT_REG_WRITE_PORT 0x0012
+#define GRAPH_DATA_PORT                  0x1F
+#define GRAPH_ADDRESS_PORT       0x1E
+#define XGI_MASK_DUAL_CHIP       0x04  /* SR3A */
+#define CRTC_ADDRESS_PORT_COLOR   0x0024
+#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013
+#define PCI_COMMAND            0x04
+#endif
+/* ~shampoo */
+
+
+#define VB_XGI301            0x0001  /*301b*/
+#define VB_XGI301B        0x0002
+#define VB_XGI302B        0x0004
+#define VB_XGI301LV     0x0008 /*301lv*/
+#define VB_XGI302LV     0x0010
+#define VB_XGI301C      0x0020       /* for 301C */
+#define  VB_NoLCD        0x8000
+/*end 301b*/
+
+#define VB_YPbPrInfo     0x07          /*301lv*/
+#define VB_YPbPr525i     0x00
+#define VB_YPbPr525p     0x01
+#define VB_YPbPr750p     0x02
+#define VB_YPbPr1080i    0x03
+
+/* #define CRT1Len 17 */
+#define LVDSCRT1Len             15
+#define CHTVRegDataLen          5
+
+/* #define ModeInfoFlag 0x07 */
+/* #define IsTextMode 0x07 */
+/* #define ModeText 0x00 */
+/* #define ModeCGA 0x01 */
+/* #define ModeEGA 0x02 */
+/* #define ModeVGA 0x03 */
+/* #define Mode15Bpp 0x04 */
+/* #define Mode16Bpp 0x05 */
+/* #define Mode24Bpp 0x06 */
+/* #define Mode32Bpp 0x07 */
+
+/* #define DACInfoFlag 0x18 */
+/* #define MemoryInfoFlag 0x1E0 */
+/* #define MemorySizeShift 0x05 */
+
+#define Charx8Dot               0x0200
+#define LineCompareOff          0x0400
+#define CRT2Mode                0x0800
+#define HalfDCLK                0x1000
+#define NoSupportSimuTV         0x2000
+#define DoubleScanMode          0x8000
+
+#define SupportAllCRT2          0x0078
+#define SupportTV               0x0008
+#define SupportHiVisionTV       0x0010
+#define SupportLCD              0x0020
+#define SupportRAMDAC2          0x0040
+#define NoSupportTV             0x0070
+#define NoSupportHiVisionTV     0x0060
+#define NoSupportLCD            0x0058
+#define SupportCHTV            0x0800
+#define SupportCRT2in301C       0x0100       /* for 301C */
+#define SupportTV1024           0x0800  /*301b*/
+#define SupportYPbPr            0x1000  /*301lv*/
+#define InterlaceMode           0x0080
+#define SyncPP                  0x0000
+#define SyncPN                  0x4000
+#define SyncNP                  0x8000
+/* #define SyncNN 0xc000 */
+#define ECLKindex0              0x0000
+#define ECLKindex1              0x0100
+#define ECLKindex2              0x0200
+#define ECLKindex3              0x0300
+#define ECLKindex4              0x0400
+
+#define SetSimuScanMode         0x0001
+#define SwitchToCRT2            0x0002
+/* #define SetCRT2ToTV 0x009C */
+#define SetCRT2ToAVIDEO         0x0004
+#define SetCRT2ToSVIDEO         0x0008
+#define SetCRT2ToSCART          0x0010
+#define SetCRT2ToLCD            0x0020
+#define SetCRT2ToRAMDAC         0x0040
+#define SetCRT2ToHiVisionTV     0x0080
+#define SetNTSCTV               0x0000
+/* #define SetPALTV 0x0100 */
+#define SetInSlaveMode          0x0200
+#define SetNotSimuMode          0x0400
+#define SetNotSimuTVMode        0x0400
+#define SetDispDevSwitch        0x0800
+#define LoadDACFlag             0x1000
+#define DisableCRT2Display      0x2000
+#define DriverMode              0x4000
+#define HotKeySwitch            0x8000
+#define SetCHTVOverScan        0x8000
+/* #define SetCRT2ToLCDA 0x8000 301b */
+#define PanelRGB18Bit           0x0100
+#define PanelRGB24Bit           0x0000
+
+#define TVOverScan              0x10
+#define TVOverScanShift         4
+#define ClearBufferFlag         0x20
+#define EnableDualEdge                 0x01            /*301b*/
+#define SetToLCDA              0x02
+
+#define YPbPrModeInfo           0x38
+/* #define YPbPrMode525i 0x00 */
+/* #define YPbPrMode525p 0x08 */
+/* #define YPbPrMode750p 0x10 */
+/* #define YPbPrMode1080i 0x18 */
+
+#define SetSCARTOutput          0x01
+#define BoardTVType             0x02
+#define  EnablePALMN           0x40
+/* #define ProgrammingCRT2 0x01 */
+/* #define TVSimuMode 0x02 */
+/* #define RPLLDIV2XO 0x04 */
+/* #define LCDVESATiming 0x08 */
+/* #define EnableLVDSDDA 0x10 */
+#define SetDispDevSwitchFlag    0x20
+#define CheckWinDos             0x40
+#define SetJDOSMode             0x80
+
+#define Panel320x480              0x07/*fstn*/
+/* [ycchen] 02/12/03 Modify for Multi-Sync. LCD Support */
+#define PanelResInfo            0x1F   /* CR36 Panel Type/LCDResInfo */
+#define PanelRefInfo            0x60
+#define Panel800x600            0x01
+#define Panel1024x768           0x02
+#define Panel1024x768x75        0x22
+#define Panel1280x1024          0x03
+#define Panel1280x1024x75       0x23
+#define Panel640x480            0x04
+#define Panel1024x600           0x05
+#define Panel1152x864           0x06
+#define Panel1280x960           0x07
+#define Panel1152x768           0x08
+#define Panel1400x1050          0x09
+#define Panel1280x768           0x0A
+#define Panel1600x1200          0x0B
+
+#define PanelRef60Hz            0x00
+#define PanelRef75Hz            0x20
+#define LCDRGB18Bit             0x01
+
+#define ExtChipTrumpion         0x06
+#define ExtChipCH7005           0x08
+#define ExtChipMitacTV          0x0a
+#define LCDNonExpanding         0x10
+#define LCDNonExpandingShift    4
+#define LCDSync                 0x20
+#define LCDSyncBit              0xe0
+#define LCDSyncShift            6
+
+/* #define DDC2DelayTime 300 */
+
+#define CRT2DisplayFlag         0x2000
+/* #define LCDDataLen 8 */
+/* #define HiTVDataLen 12 */
+/* #define TVDataLen 16 */
+/* #define SetPALTV 0x0100 */
+#define HalfDCLK                0x1000
+#define NTSCHT                  1716
+#define NTSCVT                  525
+#define PALHT                   1728
+#define PALVT                   625
+#define StHiTVHT                892
+#define StHiTVVT                1126
+#define StHiTextTVHT            1000
+#define StHiTextTVVT            1126
+#define ExtHiTVHT               2100
+#define ExtHiTVVT               1125
+
+#define St750pTVHT              1716
+#define St750pTVVT               525
+#define Ext750pTVHT             1716
+#define Ext750pTVVT              525
+#define St525pTVHT              1716
+#define St525pTVVT               525
+#define Ext525pTVHT             1716
+#define Ext525pTVVT              525
+#define St525iTVHT              1716
+#define St525iTVVT               525
+#define Ext525iTVHT             1716
+#define Ext525iTVVT              525
+
+#define VCLKStartFreq           25
+#define SoftDramType            0x80
+#define VCLK40                  0x04
+
+#define VCLK162                0x21
+
+#define LCDRGB18Bit             0x01
+#define LoadDACFlag             0x1000
+#define AfterLockCRT2           0x4000
+#define SetCRT2ToAVIDEO         0x0004
+#define SetCRT2ToSCART          0x0010
+#define Ext2StructSize          5
+
+
+#define YPbPr525iVCLK           0x03B
+#define YPbPr525iVCLK_2         0x03A
+
+#define SwitchToCRT2            0x0002
+/* #define LCDVESATiming 0x08 */
+#define SetSCARTOutput          0x01
+#define AVIDEOSense             0x01
+#define SVIDEOSense             0x02
+#define SCARTSense              0x04
+#define LCDSense                0x08
+#define Monitor1Sense           0x20
+#define Monitor2Sense           0x10
+#define HiTVSense               0x40
+#define BoardTVType             0x02
+#define HotPlugFunction         0x08
+#define StStructSize            0x06
+
+
+#define XGI_CRT2_PORT_00        0x00 - 0x030
+#define XGI_CRT2_PORT_04        0x04 - 0x030
+#define XGI_CRT2_PORT_10        0x10 - 0x30
+#define XGI_CRT2_PORT_12        0x12 - 0x30
+#define XGI_CRT2_PORT_14        0x14 - 0x30
+
+
+#define LCDNonExpanding         0x10
+#define ADR_CRT2PtrData         0x20E
+#define offset_Zurac            0x210
+#define ADR_LVDSDesPtrData      0x212
+#define ADR_LVDSCRT1DataPtr     0x214
+#define ADR_CHTVVCLKPtr         0x216
+#define ADR_CHTVRegDataPtr      0x218
+
+#define LVDSDataLen             6
+/* #define EnableLVDSDDA 0x10 */
+/* #define LVDSDesDataLen 3 */
+#define ActiveNonExpanding      0x40
+#define ActiveNonExpandingShift 6
+/* #define ActivePAL 0x20 */
+#define ActivePALShift          5
+/* #define ModeSwitchStatus 0x0F */
+#define SoftTVType              0x40
+#define SoftSettingAddr         0x52
+#define ModeSettingAddr         0x53
+
+/* #define SelectCRT1Rate 0x4 */
+
+#define _PanelType00             0x00
+#define _PanelType01             0x08
+#define _PanelType02             0x10
+#define _PanelType03             0x18
+#define _PanelType04             0x20
+#define _PanelType05             0x28
+#define _PanelType06             0x30
+#define _PanelType07             0x38
+#define _PanelType08             0x40
+#define _PanelType09             0x48
+#define _PanelType0A             0x50
+#define _PanelType0B             0x58
+#define _PanelType0C             0x60
+#define _PanelType0D             0x68
+#define _PanelType0E             0x70
+#define _PanelType0F             0x78
+
+
+#define PRIMARY_VGA       0     /* 1: XGI is primary vga 0:XGI is secondary vga */
+#define BIOSIDCodeAddr          0x235
+#define OEMUtilIDCodeAddr       0x237
+#define VBModeIDTableAddr       0x239
+#define OEMTVPtrAddr            0x241
+#define PhaseTableAddr          0x243
+#define NTSCFilterTableAddr     0x245
+#define PALFilterTableAddr      0x247
+#define OEMLCDPtr_1Addr         0x249
+#define OEMLCDPtr_2Addr         0x24B
+#define LCDHPosTable_1Addr      0x24D
+#define LCDHPosTable_2Addr      0x24F
+#define LCDVPosTable_1Addr      0x251
+#define LCDVPosTable_2Addr      0x253
+#define OEMLCDPIDTableAddr      0x255
+
+#define VBModeStructSize        5
+#define PhaseTableSize          4
+#define FilterTableSize         4
+#define LCDHPosTableSize        7
+#define LCDVPosTableSize        5
+#define OEMLVDSPIDTableSize     4
+#define LVDSHPosTableSize       4
+#define LVDSVPosTableSize       6
+
+#define VB_ModeID               0
+#define VB_TVTableIndex         1
+#define VB_LCDTableIndex        2
+#define VB_LCDHIndex            3
+#define VB_LCDVIndex            4
+
+#define OEMLCDEnable            0x0001
+#define OEMLCDDelayEnable       0x0002
+#define OEMLCDPOSEnable         0x0004
+#define OEMTVEnable             0x0100
+#define OEMTVDelayEnable        0x0200
+#define OEMTVFlickerEnable      0x0400
+#define OEMTVPhaseEnable        0x0800
+#define OEMTVFilterEnable       0x1000
+
+#define OEMLCDPanelIDSupport    0x0080
+
+/* #define LCDVESATiming 0x0001 //LCD Info CR37 */
+/* #define EnableLVDSDDA 0x0002 */
+#define EnableScalingLCD        0x0008
+#define SetPWDEnable            0x0004
+#define SetLCDtoNonExpanding    0x0010
+/* #define SetLCDPolarity 0x00E0 */
+#define SetLCDDualLink          0x0100
+#define SetLCDLowResolution     0x0200
+#define SetLCDStdMode           0x0400
+#define SetTVStdMode            0x0200
+#define SetTVLowResolution      0x0400
+/* =============================================================
+   for 310
+============================================================== */
+#define SoftDRAMType        0x80
+#define SoftSetting_OFFSET  0x52
+#define SR07_OFFSET  0x7C
+#define SR15_OFFSET  0x7D
+#define SR16_OFFSET  0x81
+#define SR17_OFFSET  0x85
+#define SR19_OFFSET  0x8D
+#define SR1F_OFFSET  0x99
+#define SR21_OFFSET  0x9A
+#define SR22_OFFSET  0x9B
+#define SR23_OFFSET  0x9C
+#define SR24_OFFSET  0x9D
+#define SR25_OFFSET  0x9E
+#define SR31_OFFSET  0x9F
+#define SR32_OFFSET  0xA0
+#define SR33_OFFSET  0xA1
+
+#define CR40_OFFSET  0xA2
+#define SR25_1_OFFSET  0xF6
+#define CR49_OFFSET  0xF7
+
+#define VB310Data_1_2_Offset  0xB6
+#define VB310Data_4_D_Offset  0xB7
+#define VB310Data_4_E_Offset  0xB8
+#define VB310Data_4_10_Offset 0xBB
+
+#define RGBSenseDataOffset    0xBD
+#define YCSenseDataOffset     0xBF
+#define VideoSenseDataOffset  0xC1
+#define OutputSelectOffset    0xF3
+
+#define ECLK_MCLK_DISTANCE  0x14
+#define VBIOSTablePointerStart    0x200
+#define StandTablePtrOffset       VBIOSTablePointerStart+0x02
+#define EModeIDTablePtrOffset     VBIOSTablePointerStart+0x04
+#define CRT1TablePtrOffset        VBIOSTablePointerStart+0x06
+#define ScreenOffsetPtrOffset     VBIOSTablePointerStart+0x08
+#define VCLKDataPtrOffset         VBIOSTablePointerStart+0x0A
+#define MCLKDataPtrOffset         VBIOSTablePointerStart+0x0E
+#define CRT2PtrDataPtrOffset      VBIOSTablePointerStart+0x10
+#define TVAntiFlickPtrOffset      VBIOSTablePointerStart+0x12
+#define TVDelayPtr1Offset         VBIOSTablePointerStart+0x14
+#define TVPhaseIncrPtr1Offset     VBIOSTablePointerStart+0x16
+#define TVYFilterPtr1Offset       VBIOSTablePointerStart+0x18
+#define LCDDelayPtr1Offset        VBIOSTablePointerStart+0x20
+#define TVEdgePtr1Offset          VBIOSTablePointerStart+0x24
+#define CRT2Delay1Offset          VBIOSTablePointerStart+0x28
+#define LCDDataDesOffset     VBIOSTablePointerStart-0x02
+#define LCDDataPtrOffset          VBIOSTablePointerStart+0x2A
+#define LCDDesDataPtrOffset     VBIOSTablePointerStart+0x2C
+#define LCDDataList            VBIOSTablePointerStart+0x22     /* add for GetLCDPtr */
+#define TVDataList             VBIOSTablePointerStart+0x36     /* add for GetTVPtr */
+/*  */
+/* Modify from 310.inc */
+/*  */
+/*  */
+
+
+#define                ShowMsgFlag                  0x20               /* SoftSetting */
+#define                ShowVESAFlag                 0x10
+#define                HotPlugFunction              0x08
+#define                ModeSoftSetting              0x04
+#define                TVSoftSetting                0x02
+#define                LCDSoftSetting               0x01
+
+#define                GatingCRTinLCDA              0x10
+#define                SetHiTVOutput                0x08
+#define                SetYPbPrOutput               0x04
+#define                BoardTVType                  0x02
+#define                SetSCARTOutput               0x01
+
+#define                ModeSettingYPbPr             0x02               /* TVModeSetting, Others as same as CR30 */
+
+/* TVModeSetting same as CR35 */
+
+/* LCDModeSetting same as CR37 */
+
+#define                EnableNewTVFont              0x10               /* MiscCapability */
+
+#define                EnableLCDOutput              0x80               /* LCDCfgSetting */
+
+#define                SoftDRAMType                 0x80               /* DRAMSetting */
+#define                SoftDRAMConfig               0x40
+#define                MosSelDRAMType               0x20
+#define                SDRAM                        000h
+#define                SGRAM                        0x01
+#define                ESDRAM                       0x02
+
+#define                EnableAGPCfgSetting          0x01               /* AGPCfgSetting */
+
+/* ---------------- SetMode Stack */
+#define                CRT1Len                      15
+#define                VCLKLen                      4
+#define                DefThreshold                 0x0100
+#define                ExtRegsSize                  (57+8+37+70+63+28+768+1)/64+1
+
+#define                VGA_XGI315                   0x0001       /* VGA Type Info */
+#define                VGA_SNewis315e                  0x0002       /* 315 series */
+#define                VGA_XGI550                   0x0004
+#define                VGA_XGI640                   0x0008
+#define                VGA_XGI740                   0x0010
+#define                VGA_XGI650                   0x0020
+#define                VGA_XGI650M                  0x0040
+#define                VGA_XGI651                   0x0080
+#define                VGA_XGI340                   0x0001       /* 340 series */
+#define                VGA_XGI330                   0x0001       /* 330 series */
+#define                VGA_XGI660                   0x0001       /* 660 series */
+
+#define                VB_XGI301                    0x0001       /* VB Type Info */
+#define                VB_XGI301B                   0x0002       /* 301 series */
+#define                VB_XGI302B                   0x0004
+#define                VB_NoLCD                     0x8000
+#define                VB_XGI301LV                  0x0008
+#define                VB_XGI302LV                  0x0010
+#define                VB_LVDS_NS                   0x0001       /* 3rd party chip */
+#define                VB_CH7017                    0x0002
+#define         VB_CH7007                    0x0080       /* [Billy] 07/05/03 */
+/* #define VB_LVDS_SI 0x0004 */
+
+#define                ModeInfoFlag                 0x0007
+#define                IsTextMode                   0x0007
+#define                ModeText                     0x0000
+#define                ModeCGA                      0x0001
+#define                ModeEGA                      0x0002       /* 16 colors mode */
+#define                ModeVGA                      0x0003       /* 256 colors mode */
+#define                Mode15Bpp                    0x0004       /* 15 Bpp Color Mode */
+#define                Mode16Bpp                    0x0005       /* 16 Bpp Color Mode */
+#define                Mode24Bpp                    0x0006       /* 24 Bpp Color Mode */
+#define                Mode32Bpp                    0x0007       /* 32 Bpp Color Mode */
+
+#define                DACInfoFlag                  0x0018
+#define                MONODAC                      0x0000
+#define                CGADAC                       0x0008
+#define                EGADAC                       0x0010
+#define                VGADAC                       0x0018
+
+#define                MemoryInfoFlag               0x01e0
+#define                MemorySizeShift              5
+#define                Need1MSize                   0x0000
+#define                Need2MSize                   0x0020
+#define                Need4MSize                   0x0060
+#define                Need8MSize                   0x00e0
+#define                Need16MSize                  0x01e0
+
+#define                Charx8Dot                    0x0200
+#define                LineCompareOff               0x0400
+#define                CRT2Mode                     0x0800
+#define                HalfDCLK                     0x1000
+#define                NoSupportSimuTV              0x2000
+#define                DoubleScanMode               0x8000
+
+/* -------------- Ext_InfoFlag */
+#define                SupportModeInfo              0x0007
+#define                Support256                   0x0003
+#define                Support15Bpp                 0x0004
+#define                Support16Bpp                 0x0005
+#define                Support24Bpp                 0x0006
+#define                Support32Bpp                 0x0007
+
+#define                SupportAllCRT2               0x0078
+#define                SupportTV                    0x0008
+#define                SupportHiVisionTV            0x0010
+#define                SupportLCD                   0x0020
+#define                SupportRAMDAC2               0x0040
+#define                NoSupportTV                  0x0070
+#define                NoSupportHiVisionTV          0x0060
+#define                NoSupportLCD                 0x0058
+#define                SupportTV1024                0x0800       /* 301btest */
+#define                SupportYPbPr                 0x1000       /* 301lv */
+#define                InterlaceMode                0x0080
+#define                SyncPP                       0x0000
+#define                SyncPN                       0x4000
+#define                SyncNP                       0x8000
+#define                SyncNN                       0xC000
+
+/* -------------- SetMode Stack/Scratch */
+#define                SetSimuScanMode              0x0001       /* VBInfo/CR30 & CR31 */
+#define                SwitchToCRT2                 0x0002
+#define                SetCRT2ToTV1                 0x009C
+#define                SetCRT2ToTV                  0x089C
+#define                SetCRT2ToAVIDEO              0x0004
+#define                SetCRT2ToSVIDEO              0x0008
+#define                SetCRT2ToSCART               0x0010
+#define                SetCRT2ToLCD                 0x0020
+#define                SetCRT2ToRAMDAC              0x0040
+#define                SetCRT2ToHiVisionTV          0x0080
+#define                SetCRT2ToLCDA                0x0100
+#define                SetInSlaveMode               0x0200
+#define                SetNotSimuMode               0x0400
+#define                HKEventMode                  0x0800
+#define                SetCRT2ToYPbPr               0x0800
+#define                LoadDACFlag                  0x1000
+#define                DisableCRT2Display           0x2000
+#define                DriverMode                   0x4000
+#define                SetCRT2ToDualEdge            0x8000
+#define                HotKeySwitch                 0x8000
+
+#define                ProgrammingCRT2              0x0001       /* Set Flag */
+#define                EnableVCMode                 0x0002
+#define                SetHKEventMode               0x0004
+#define                ReserveTVOption              0x0008
+#define                DisableRelocateIO            0x0010
+#define                Win9xDOSMode                 0x0020
+#define                JDOSMode                     0x0040
+/* #define SetWin9xforJap 0x0080 // not used now */
+/* #define SetWin9xforKorea 0x0100 // not used now */
+#define                GatingCRT                    0x0800
+#define                DisableChB                   0x1000
+#define                EnableChB                    0x2000
+#define                DisableChA                   0x4000
+#define                EnableChA                    0x8000
+
+#define                SetNTSCTV                    0x0000       /* TV Info */
+#define                SetPALTV                     0x0001
+#define                SetNTSCJ                     0x0002
+#define                SetPALMTV                    0x0004
+#define                SetPALNTV                    0x0008
+#define                SetCHTVUnderScan             0x0000
+/* #define SetCHTVOverScan 0x0010 */
+#define                SetYPbPrMode525i             0x0020
+#define                SetYPbPrMode525p             0x0040
+#define                SetYPbPrMode750p             0x0080
+#define                SetYPbPrMode1080i            0x0100
+#define                SetTVStdMode                 0x0200
+#define                SetTVLowResolution           0x0400
+#define                SetTVSimuMode                0x0800
+#define                TVSimuMode                   0x0800
+#define                RPLLDIV2XO                   0x1000
+#define                NTSC1024x768                 0x2000
+#define                SetTVLockMode                0x4000
+
+#define                LCDVESATiming                0x0001       /* LCD Info/CR37 */
+#define                EnableLVDSDDA                0x0002
+#define                EnableScalingLCD             0x0008
+#define                SetPWDEnable                 0x0004
+#define                SetLCDtoNonExpanding         0x0010
+#define                SetLCDPolarity               0x00e0
+#define                SetLCDDualLink               0x0100
+#define                SetLCDLowResolution          0x0200
+#define                SetLCDStdMode                0x0400
+
+#define                DefaultLCDCap                0x80ea       /* LCD Capability shampoo */
+#define                RLVDSDHL00                   0x0000
+#define                RLVDSDHL01                   0x0001
+#define                RLVDSDHL10                   0x0002       /* default */
+#define                RLVDSDHL11                   0x0003
+#define                EnableLCD24bpp               0x0004       /* default */
+#define                DisableLCD24bpp              0x0000
+#define                RLVDSClkSFT0                 0x0000
+#define                RLVDSClkSFT1                 0x0008       /* default */
+#define                EnableLVDSDCBal              0x0010
+#define                DisableLVDSDCBal             0x0000       /* default */
+#define                SinglePolarity               0x0020       /* default */
+#define                MultiPolarity                0x0000
+#define                LCDPolarity                  0x00c0       /* default: SyncNN */
+#define                LCDSingleLink                0x0000       /* default */
+#define                LCDDualLink                  0x0100
+#define                EnableSpectrum               0x0200
+#define                DisableSpectrum              0x0000       /* default */
+#define                PWDEnable                    0x0400
+#define                PWDDisable                   0x0000       /* default */
+#define                PWMEnable                    0x0800
+#define                PWMDisable                   0x0000       /* default */
+#define                EnableVBCLKDRVLOW            0x4000
+#define                EnableVBCLKDRVHigh           0x0000       /* default */
+#define                EnablePLLSPLOW               0x8000
+#define                EnablePLLSPHigh              0x0000       /* default */
+
+#define                LCDBToA                      0x20               /* LCD SetFlag */
+#define                StLCDBToA                    0x40
+#define                LockLCDBToA                  0x80
+#define        LCDToFull                    0x10
+#define                AVIDEOSense                  0x01               /* CR32 */
+#define                SVIDEOSense                  0x02
+#define                SCARTSense                   0x04
+#define                LCDSense                     0x08
+#define                Monitor2Sense                0x10
+#define                Monitor1Sense                0x20
+#define                HiTVSense                    0x40
+
+#ifdef                   NewScratch
+#define                YPbPrSense                   0x80    /* NEW SCRATCH */
+#endif
+
+#define                TVSense                      0xc7
+
+#define                TVOverScan                   0x10               /* CR35 */
+#define                TVOverScanShift              4
+
+#ifdef                   NewScratch
+#define                NTSCMode                     0x00
+#define                PALMode                      0x00
+#define                NTSCJMode                    0x02
+#define                PALMNMode                    0x0c
+#define                YPbPrMode                    0xe0
+#define                YPbPrMode525i                0x00
+#define                YPbPrMode525p                0x20
+#define                YPbPrMode750p                0x40
+#define                YPbPrMode1080i               0x60
+#else                    /* Old Scratch */
+#define                ClearBufferFlag              0x20
+#endif
+
+
+#define                LCDRGB18Bit                  0x01               /* CR37 */
+#define                LCDNonExpanding              0x10
+#define                LCDNonExpandingShift         4
+#define                LCDSync                      0x20
+#define                LCDSyncBit                   0xe0               /* H/V polarity & sync ID */
+#define                LCDSyncShift                 6
+
+#ifdef                   NewScratch
+#define                ScalingLCD                   0x08
+#else                    /* Old Scratch */
+#define                ExtChipType                  0x0e
+#define                ExtChip301                   0x02
+#define                ExtChipLVDS                  0x04
+#define                ExtChipCH7019                0x06
+#define                ScalingLCD                   0x10
+#endif
+
+#define                EnableDualEdge               0x01               /* CR38 */
+#define                SetToLCDA                    0x02
+#ifdef                   NewScratch
+#define                SetYPbPr                     0x04
+#define                DisableChannelA              0x08
+#define                DisableChannelB              0x10
+#define                ExtChipType                  0xe0
+#define                ExtChip301                   0x20
+#define                ExtChipLVDS                  0x40
+#define                ExtChipCH7019                0x60
+#else                    /* Old Scratch */
+#define                YPbPrSense                   0x04
+#define                SetYPbPr                     0x08
+#define                YPbPrMode                    0x30
+#define                YPbPrMode525i                0x00
+#define                YPbPrMode525p                0x10
+#define                YPbPrMode750p                0x20
+#define                YPbPrMode1080i               0x30
+#define                PALMNMode                    0xc0
+#endif
+
+#define                BacklightControlBit          0x01               /* CR3A */
+#define                Win9xforJap                  0x40
+#define                Win9xforKorea                0x80
+
+#define                ForceMDBits                  0x07               /* CR3B */
+#define                ForceMD_JDOS                 0x00
+#define                ForceMD_640x400T             0x01
+#define                ForceMD_640x350T             0x02
+#define                ForceMD_720x400T             0x03
+#define                ForceMD_640x480E             0x04
+#define                ForceMD_640x400E             0x05
+#define                ForceP1Bit                   0x10
+#define                ForceP2Bit                   0x20
+#define                EnableForceMDinBIOS          0x40
+#define                EnableForceMDinDrv           0x80
+
+#ifdef                   NewScratch                      /* New Scratch */
+/* ---------------------- VUMA Information */
+#define                LCDSettingFromCMOS           0x04               /* CR3C */
+#define                TVSettingFromCMOS            0x08
+#define                DisplayDeviceFromCMOS        0x10
+#define                HKSupportInSBIOS             0x20
+#define                OSDSupportInSBIOS            0x40
+#define                DisableLogo                  0x80
+
+/* ---------------------- HK Evnet Definition */
+#define                HKEvent                      0x0f               /* CR3D */
+#define                HK_ModeSwitch                0x01
+#define                HK_Expanding                 0x02
+#define                HK_OverScan                  0x03
+#define                HK_Brightness                0x04
+#define                HK_Contrast                  0x05
+#define                HK_Mute                      0x06
+#define                HK_Volume                    0x07
+#define                ModeSwitchStatus             0xf0
+#define                ActiveCRT1                   0x10
+#define                ActiveLCD                    0x0020
+#define                ActiveTV                     0x40
+#define                ActiveCRT2                   0x80
+
+#define                TVSwitchStatus               0x1f               /* CR3E */
+#define                ActiveAVideo                 0x01
+#define                ActiveSVideo                 0x02
+#define                ActiveSCART                  0x04
+#define                ActiveHiTV                   0x08
+#define                ActiveYPbPr                  0x10
+
+#define                EnableHKEvent                0x01               /* CR3F */
+#define                EnableOSDEvent               0x02
+#define                StartOSDEvent                0x04
+#define                IgnoreHKEvent                0x08
+#define                IgnoreOSDEvent               0x10
+#else                    /* Old Scratch */
+#define                OSD_SBIOS                    0x02       /* SR17 */
+#define                DisableLogo                  0x04
+#define                SelectKDOS                   0x08
+#define                KorWinMode                   0x10
+#define                KorMode3Bit                  0x0020
+#define                PSCCtrlBit                  0x40
+#define                NPSCCtrlBitShift             6
+#define                BlueScreenBit                0x80
+
+#define                HKEvent                      0x0f       /* CR79 */
+#define                HK_ModeSwitch                0x01
+#define                HK_Expanding                 0x02
+#define                HK_OverScan                  0x03
+#define                HK_Brightness                0x04
+#define                HK_Contrast                  0x05
+#define                HK_Mute                      0x06
+#define                HK_Volume                    0x07
+#define                ActivePAL                    0x0020
+#define                ActivePALShift               5
+#define                ActiveNonExpanding           0x40
+#define                ActiveNonExpandingShift      6
+#define                ActiveOverScan               0x80
+#define                ActiveOverScanShift          7
+
+#define                ModeSwitchStatus             0x0b       /* SR15 */
+#define                ActiveCRT1                   0x01
+#define                ActiveLCD                    0x02
+#define                ActiveCRT2                   0x08
+
+#define                TVSwitchStatus               0xf0       /* SR16 */
+#define                TVConfigShift                3
+#define                ActiveTV                     0x01
+#define                ActiveYPbPr                  0x04
+#define                ActiveAVideo                 0x10
+#define                ActiveSVideo                 0x0020
+#define                ActiveSCART                  0x40
+#define                ActiveHiTV                   0x80
+
+#define                EnableHKEvent                0x01       /* CR7A */
+#define                EnableOSDEvent               0x02
+#define                StartOSDEvent                0x04
+#define                CMOSSupport                  0x08
+#define                HotKeySupport                0x10
+#define                IngoreHKOSDEvent             0x20
+#endif
+
+/* //------------- Misc. Definition */
+#define                SelectCRT1Rate               00h
+/* #define SelectCRT2Rate 04h */
+
+#define                DDC1DelayTime                1000
+#ifdef           TRUMPION
+#define                DDC2DelayTime                15
+#else
+#define                DDC2DelayTime                150
+#endif
+
+#define                R_FACTOR                     04Dh
+#define                G_FACTOR                     097h
+#define                B_FACTOR                     01Ch
+/* --------------------------------------------------------- */
+/* translated from asm code 301def.h */
+/*  */
+/* --------------------------------------------------------- */
+#define                LCDDataLen                   8
+#define                HiTVDataLen                  12
+#define                TVDataLen                    12
+#define                LVDSCRT1Len_H                8
+#define                LVDSCRT1Len_V                7
+#define                LVDSDataLen                  6
+#define                LVDSDesDataLen               6
+#define                LCDDesDataLen                6
+#define                LVDSDesDataLen2              8
+#define                LCDDesDataLen2               8
+#define                CHTVRegLen                   16
+#define                CHLVRegLen                   12
+
+#define                StHiTVHT                     892
+#define                StHiTVVT                     1126
+#define                StHiTextTVHT                 1000
+#define                StHiTextTVVT                 1126
+#define                ExtHiTVHT                    2100
+#define                ExtHiTVVT                    1125
+#define                NTSCHT                       1716
+#define                NTSCVT                        525
+#define                NTSC1024x768HT               1908
+#define                NTSC1024x768VT                525
+#define                PALHT                        1728
+#define                PALVT                         625
+
+#define                YPbPrTV525iHT                1716            /* YPbPr */
+#define                YPbPrTV525iVT                 525
+#define                YPbPrTV525pHT                1716
+#define                YPbPrTV525pVT                 525
+#define                YPbPrTV750pHT                1650
+#define                YPbPrTV750pVT                 750
+
+#define                CRT2VCLKSel                  0xc0
+
+#define                CRT2Delay1                   0x04            /* XGI301 */
+#define                CRT2Delay2                   0x0A            /* 301B,302 */
+
+
+#define                VCLK25_175           0x00
+#define                VCLK28_322           0x01
+#define                VCLK31_5             0x02
+#define                VCLK36               0x03
+#define                VCLK40               0x04
+#define                VCLK43_163           0x05
+#define                VCLK44_9             0x06
+#define                VCLK49_5             0x07
+#define                VCLK50               0x08
+#define                VCLK52_406           0x09
+#define                VCLK56_25            0x0A
+#define                VCLK65               0x0B
+#define                VCLK67_765           0x0C
+#define                VCLK68_179           0x0D
+#define                VCLK72_852           0x0E
+#define                VCLK75               0x0F
+#define                VCLK75_8             0x10
+#define                VCLK78_75            0x11
+#define                VCLK79_411           0x12
+#define                VCLK83_95            0x13
+#define                VCLK84_8             0x14
+#define                VCLK86_6             0x15
+#define                VCLK94_5             0x16
+#define                VCLK104_998          0x17
+#define                VCLK105_882          0x18
+#define                VCLK108_2            0x19
+#define                VCLK109_175          0x1A
+#define                VCLK113_309          0x1B
+#define                VCLK116_406          0x1C
+#define                VCLK132_258          0x1D
+#define                VCLK135_5            0x1E
+#define                VCLK139_054          0x1F
+#define                VCLK157_5            0x20
+#define                VCLK162              0x21
+#define                VCLK175              0x22
+#define                VCLK189              0x23
+#define                VCLK194_4            0x24
+#define                VCLK202_5            0x25
+#define                VCLK229_5            0x26
+#define                VCLK234              0x27
+#define                VCLK252_699          0x28
+#define                VCLK254_817          0x29
+#define                VCLK265_728          0x2A
+#define                VCLK266_952          0x2B
+#define                VCLK269_655          0x2C
+#define                VCLK272_042          0x2D
+#define                VCLK277_015          0x2E
+#define                VCLK286_359          0x2F
+#define                VCLK291_132          0x30
+#define                VCLK291_766          0x31
+#define                VCLK309_789          0x32
+#define                VCLK315_195          0x33
+#define                VCLK323_586          0x34
+#define                VCLK330_615          0x35
+#define                VCLK332_177          0x36
+#define                VCLK340_477          0x37
+#define                VCLK375_847          0x38
+#define                VCLK388_631          0x39
+#define                VCLK125_999          0x51
+#define                VCLK148_5            0x52
+#define                VCLK178_992          0x54
+#define                VCLK217_325          0x55
+#define                VCLK299_505          0x56
+#define                YPbPr750pVCLK        0x57
+
+#define                TVVCLKDIV2              0x3A
+#define                TVVCLK                  0x3B
+#define                HiTVVCLKDIV2          0x3C
+#define                HiTVVCLK              0x3D
+#define                HiTVSimuVCLK          0x3E
+#define                HiTVTextVCLK          0x3F
+#define                VCLK39_77              0x40
+/* #define YPbPr750pVCLK 0x0F */
+#define                YPbPr525pVCLK           0x3A
+/* #define ;;YPbPr525iVCLK 0x3B */
+/* #define ;;YPbPr525iVCLK_2 0x3A */
+#define                NTSC1024VCLK         0x41
+#define                VCLK25_175_41        0x42                  /* ; ScaleLCD */
+#define                VCLK25_175_42        0x43
+#define                VCLK28_322_43        0x44
+#define                VCLK40_44            0x45
+#define                VCLKQVGA_1           0x46                   /* ; QVGA */
+#define                VCLKQVGA_2           0x47
+#define                VCLKQVGA_3           0x48
+#define                VCLK35_2             0x49                    /* ; 800x480 */
+#define                VCLK122_61           0x4A
+#define                VCLK80_350           0x4B
+#define                VCLK107_385          0x4C
+
+#define                CHTVVCLK30_2         0x50                 /* ;;CHTV */
+#define                CHTVVCLK28_1         0x51
+#define                CHTVVCLK43_6         0x52
+#define                CHTVVCLK26_4         0x53
+#define                CHTVVCLK24_6         0x54
+#define                CHTVVCLK47_8         0x55
+#define                CHTVVCLK31_5         0x56
+#define                CHTVVCLK26_2         0x57
+#define                CHTVVCLK39           0x58
+#define                CHTVVCLK36           0x59
+
+#define                CH7007TVVCLK30_2     0x00                 /* [Billy] 2007/05/18 For CH7007 */
+#define                CH7007TVVCLK28_1     0x01
+#define                CH7007TVVCLK43_6     0x02
+#define                CH7007TVVCLK26_4     0x03
+#define                CH7007TVVCLK24_6     0x04
+#define                CH7007TVVCLK47_8     0x05
+#define                CH7007TVVCLK31_5     0x06
+#define                CH7007TVVCLK26_2     0x07
+#define                CH7007TVVCLK39       0x08
+#define                CH7007TVVCLK36       0x09
+
+#define                RES320x200                   0x00
+#define                RES320x240                   0x01
+#define                RES400x300                   0x02
+#define                RES512x384                   0x03
+#define                RES640x400                   0x04
+#define                RES640x480x60                0x05
+#define                RES640x480x72                0x06
+#define                RES640x480x75                0x07
+#define                RES640x480x85                0x08
+#define                RES640x480x100               0x09
+#define                RES640x480x120               0x0A
+#define                RES640x480x160               0x0B
+#define                RES640x480x200               0x0C
+#define                RES800x600x56                0x0D
+#define                RES800x600x60                0x0E
+#define                RES800x600x72                0x0F
+#define                RES800x600x75                0x10
+#define                RES800x600x85                0x11
+#define                RES800x600x100               0x12
+#define                RES800x600x120               0x13
+#define                RES800x600x160               0x14
+#define                RES1024x768x43               0x15
+#define                RES1024x768x60               0x16
+#define                RES1024x768x70               0x17
+#define                RES1024x768x75               0x18
+#define                RES1024x768x85               0x19
+#define                RES1024x768x100              0x1A
+#define                RES1024x768x120              0x1B
+#define                RES1280x1024x43              0x1C
+#define                RES1280x1024x60              0x1D
+#define                RES1280x1024x75              0x1E
+#define                RES1280x1024x85              0x1F
+#define                RES1600x1200x60              0x20
+#define                RES1600x1200x65              0x21
+#define                RES1600x1200x70              0x22
+#define                RES1600x1200x75              0x23
+#define                RES1600x1200x85              0x24
+#define                RES1600x1200x100             0x25
+#define                RES1600x1200x120             0x26
+#define                RES1920x1440x60              0x27
+#define                RES1920x1440x65              0x28
+#define                RES1920x1440x70              0x29
+#define                RES1920x1440x75              0x2A
+#define                RES1920x1440x85              0x2B
+#define                RES1920x1440x100             0x2C
+#define                RES2048x1536x60              0x2D
+#define                RES2048x1536x65              0x2E
+#define                RES2048x1536x70              0x2F
+#define                RES2048x1536x75              0x30
+#define                RES2048x1536x85              0x31
+#define                RES800x480x60                0x32
+#define                RES800x480x75                0x33
+#define                RES800x480x85                0x34
+#define                RES1024x576x60               0x35
+#define                RES1024x576x75               0x36
+#define                RES1024x576x85               0x37
+#define                RES1280x720x60               0x38
+#define                RES1280x720x75               0x39
+#define                RES1280x720x85               0x3A
+#define                RES1280x960x60               0x3B
+#define                RES720x480x60                0x3C
+#define                RES720x576x56                0x3D
+#define                RES856x480x79I               0x3E
+#define                RES856x480x60                0x3F
+#define                RES1280x768x60               0x40
+#define                RES1400x1050x60              0x41
+#define                RES1152x864x60               0x42
+#define                RES1152x864x75               0x43
+#define                RES1024x768x160              0x44
+#define                RES1280x960x75               0x45
+#define                RES1280x960x85               0x46
+#define                RES1280x960x120              0x47
+
+#define        LFBDRAMTrap                  0x30
+#endif
diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
new file mode 100644 (file)
index 0000000..49b39ee
--- /dev/null
@@ -0,0 +1,1370 @@
+#include "osdef.h"
+
+
+
+
+#ifdef WIN2000
+
+#include <dderror.h>
+#include <devioctl.h>
+#include <miniport.h>
+#include <ntddvdeo.h>
+#include <video.h>
+#include "xgiv.h"
+#include "dd_i2c.h"
+#include "tools.h"
+#endif /* WIN2000 */
+
+#ifdef LINUX_XF86
+#include "xf86.h"
+#include "xf86PciInfo.h"
+#include "xgi.h"
+#include "xgi_regs.h"
+#endif
+
+#ifdef LINUX_KERNEL
+#include <linux/version.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include "XGIfb.h"
+/*#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <video/XGIfb.h>
+#else
+#include <linux/XGIfb.h>
+#endif*/
+#endif
+
+
+
+#include "vb_def.h"
+#include "vgatypes.h"
+#include "vb_struct.h"
+#include "vb_util.h"
+#include "vb_setmode.h"
+#include "vb_ext.h"
+extern   UCHAR XGI330_SoftSetting;
+extern   UCHAR XGI330_OutputSelect;
+extern   USHORT XGI330_RGBSenseData2;
+extern   USHORT XGI330_YCSenseData2;
+extern   USHORT XGI330_VideoSenseData2;
+#ifdef WIN2000
+extern   UCHAR SenseCHTV(PHW_DEVICE_EXTENSION pHWDE);       /* 2007/05/17 Billy */
+#endif
+void     XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
+BOOLEAN  XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo);
+USHORT   XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGINew_GetLCDDDCInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+void XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE ) ;
+BOOLEAN  XGINew_BridgeIsEnable(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo );
+BOOLEAN  XGINew_Sense(USHORT tempbx,USHORT tempcx, PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+
+/**************************************************************
+       Dynamic Sense
+*************************************************************/
+
+void XGI_WaitDisplay(void);
+BOOLEAN XGI_Is301C(PVB_DEVICE_INFO);
+BOOLEAN XGI_Is301LV(PVB_DEVICE_INFO);
+
+#ifdef WIN2000
+UCHAR XGI_SenseLCD(PHW_DEVICE_EXTENSION, PVB_DEVICE_INFO);
+UCHAR XGI_GetLCDDDCInfo(PHW_DEVICE_EXTENSION,PVB_DEVICE_INFO);
+
+extern BOOL bGetDdcInfo(
+PHW_DEVICE_EXTENSION  pHWDE,
+ULONG                 ulWhichOne,
+PUCHAR                pjQueryBuffer,
+ULONG                 ulBufferSize
+   );
+
+#endif
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_Is301B */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_Is301B( PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT flag ;
+
+    flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) ;
+
+    if ( flag > 0x0B0 )
+        return( 0 ) ;  /* 301b */
+    else
+        return( 1 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_Is301C */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_Is301C( PVB_DEVICE_INFO pVBInfo )
+{
+    if ( ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) & 0xF0 ) == 0xC0 )
+        return( 1 ) ;
+
+    if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) >= 0xD0 )
+    {
+        if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) == 0xE0 )
+            return( 1 ) ;
+    }
+
+    return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_Is301LV */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_Is301LV( PVB_DEVICE_INFO pVBInfo )
+{
+    if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) >= 0xD0 )
+    {
+        if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) == 0xFF )
+        {
+            return( 1 ) ;
+        }
+    }
+    return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_Sense */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_Sense(  USHORT tempbx , USHORT tempcx, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT temp , i , tempch ;
+
+    temp = tempbx & 0xFF ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
+    temp = ( tempbx & 0xFF00 ) >> 8 ;
+    temp |= ( tempcx & 0x00FF ) ;
+    XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
+
+    for( i = 0 ; i < 10 ; i++ )
+        XGI_LongWait( pVBInfo) ;
+
+    tempch = ( tempcx & 0x7F00 ) >> 8 ;
+    temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
+    temp = temp ^ ( 0x0E ) ;
+    temp &= tempch ;
+
+    if ( temp > 0 )
+        return( 1 ) ;
+    else
+        return( 0 ) ;
+}
+
+#ifdef WIN2000
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SenseLCD */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGI_SenseLCD( PHW_DEVICE_EXTENSION pHWDE, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempax , tempbx , tempcx ;
+    UCHAR SoftSetting = XGI330_SoftSetting ;
+
+    if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV ) )
+        return( 1 ) ;
+
+
+    if ( SoftSetting & HotPlugFunction )       /* Hot Plug Detection */
+    {
+        XGINew_SetRegAND( pVBInfo->Part4Port , 0x0F , 0x3F ) ;
+        tempbx = 0 ;
+        tempcx = 0x9010 ;
+        if ( XGINew_Sense( tempbx , tempcx, pVBInfo ) )
+            return( 1 ) ;
+
+        return( 0 ) ;
+    }
+    else       /* Get LCD Info from EDID */
+        return(XGI_GetLCDDDCInfo(pHWDE, pVBInfo));
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLCDDDCInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGI_GetLCDDDCInfo( PHW_DEVICE_EXTENSION pHWDE , PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR tempah , tempbl , tempbh ;
+    USHORT tempbx , temp ;
+    UCHAR pjEDIDBuf[ 256 ] ;
+    ULONG ulBufferSize = 256 ;
+    UCHAR bMASK_OUTPUTSTATE_CRT2LCD = 2 ; /* 0423 shampoo */
+
+    bGetDdcInfo( pHWDE , MASK_OUTPUTSTATE_CRT2LCD , pjEDIDBuf , ulBufferSize ) ;
+    if ( ( *( ( PULONG )pjEDIDBuf ) == 0xFFFFFF00 ) && ( *( ( PULONG )( pjEDIDBuf + 4 ) ) == 0x00FFFFFF ) )
+    {
+        tempah = Panel1024x768 ;
+        tempbl=( *( pjEDIDBuf + 0x3A ) ) & 0xf0 ;
+
+        if ( tempbl != 0x40 )
+        {
+            tempah = Panel1600x1200 ;
+            if ( tempbl != 0x60 )
+            {
+                tempah = Panel1280x1024 ;
+                tempbh = ( *( pjEDIDBuf + 0x3B ) ) ;
+                if ( tempbh != 0x00 )
+                {
+                    tempah = Panel1280x960 ;
+                    if ( tempbh != 0x0C0 )
+                    {
+                        tempbx = ( ( *( pjEDIDBuf + 0x24 ) ) << 8 ) | ( *( pjEDIDBuf + 0x23 ) ) ;
+                        tempah = Panel1280x1024 ;
+                        if ( !( tempbx & 0x0100 ) )
+                        {
+                            tempah = Panel1024x768 ;
+                            if ( !( tempbx & 0x0E00 ) )
+                            {
+                                tempah = Panel1280x1024 ;
+                            }
+                        }
+                    }
+
+                    if ( tempbx & 0x00FF )
+                    {
+                        temp = ScalingLCD ;
+                        XGINew_SetRegOR( pVBInfo->P3d4 , 0x37 , temp ) ;
+                    }
+                }
+            }
+        }
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , ( ~0x07 ) , tempah ) ;
+        tempah = ( ( *( pjEDIDBuf + 0x47 ) ) & 0x06 ) ;                /* Polarity */
+        tempah = ( tempah ^ 0x06 ) << 4 ;
+        tempah |= LCDSync ;
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ( ~LCDSyncBit ) , tempah ) ;
+        tempbh= XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
+        tempbh &= 0x07 ;
+        if ( tempbh == Panel1280x960 )
+            XGINew_SetRegAND( pVBInfo->P3d4 , 0x37 , 0x0E ) ;
+    }
+    else if ( *pjEDIDBuf == 0x20 )
+    {
+        tempah = Panel1024x768 ;
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , ( ~0x07 ) , tempah ) ;
+    }
+    else
+    {
+        return( 0 ) ;
+    }
+
+    return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DySense */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_DySense( PHW_DEVICE_EXTENSION pHWDE , PUCHAR ujConnectStatus)
+{
+    UCHAR pre_CRD,pre_SR1E , pre_Part2_0 , pre_Part4_D ;
+    USHORT tempax , tempbx , tempcx , pushax , temp ;
+    VB_DEVICE_INFO VBINF;
+    PVB_DEVICE_INFO pVBInfo = &VBINF;
+    UCHAR OutputSelect = XGI330_OutputSelect ;
+    PXGI_HW_DEVICE_INFO HwDeviceExtension= pHWDE->pXGIHWDE ;
+    UCHAR   bConnectStatus = 0 ;
+    pVBInfo->BaseAddr = HwDeviceExtension->pjIOAddress ;
+    pVBInfo->ROMAddr  = pHWDE->pjVirtualRomBase ;
+
+    pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+    pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+    pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+    pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+    pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+    pushax = XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ;  /* 0512 Fix Dysense hanged */
+    temp = ( pushax & 0x00FF ) | 0x80 ;
+    XGINew_SetRegOR( pVBInfo->P3d4 , 0x17 , temp ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
+    /* beginning of dynamic sense CRT1 */
+
+    pVBInfo->IF_DEF_CH7007 = 0;
+    if (pHWDE->bCH7007)
+    {
+       InitTo330Pointer( pHWDE->pXGIHWDE->jChipType, pVBInfo ) ;
+        HwDeviceExtension->pDevice = (PVOID)pHWDE;
+        pVBInfo->IF_DEF_CH7007 = 1;
+        /* [Billy] 2007/05/14 For CH7007 */
+        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+        {
+           bConnectStatus = SenseCHTV(HwDeviceExtension->pDevice) ; /* 07/05/28 */
+           XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~0x03 , (UCHAR)bConnectStatus ) ;
+        }
+    }
+    if(( pHWDE->jChipID >= XG40 ) || ( pHWDE->jChipID >= XG20 ))
+    {
+
+        if ( pHWDE->jChipID >= XG40 )
+           XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x4A ) ;     /* write sense pattern 30->4a */
+       else
+            XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x5F ) ;    /* write sense pattern */
+
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x53 , 0xFF , 0x02 ) ;     /* enable sense DAC */
+        XGI_WaitDisply(pVBInfo) ;
+
+        if(XGINew_GetReg2( pVBInfo->P3c2 ) & 0x10 )
+            bConnectStatus |= Monitor1Sense ;
+
+        XGINew_SetRegAND( pVBInfo->P3d4 , 0x53 , 0xFD ) ;      /* disable sense DAC */
+        XGINew_SetRegAND( pVBInfo->P3d4 , 0x57 , 0x00 ) ;      /* clear sense pattern */
+
+
+        /* ---------- End of dynamic sense CRT1 ----------- */
+
+        /* ---------- beginning of dynamic sense VB ------------ */
+        pre_SR1E = XGINew_GetReg1( pVBInfo->P3c4 , 0x1E ) ;
+        XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x20 ) ;       /* Enable CRT2,work-a-round for 301B/301LV/302LV */
+        pre_Part2_0 = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
+        pre_Part4_D = XGINew_GetReg1( pVBInfo->Part4Port , 0x0D ) ;
+
+        if ( XGI_Is301C( pVBInfo ) )   /* 301C only */
+            XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~0x07 , 0x01 ) ;   /* Set Part4 0x0D D[2:0] to 001b */
+
+        /* tempax = 0 ; */
+        if ( !XGI_Is301LV( pVBInfo ) )
+        {
+           tempbx = XGI330_RGBSenseData2 ;
+            tempcx = 0x0E08 ;
+            if(XGINew_Sense( tempbx , tempcx, pVBInfo ) )
+            {
+                bConnectStatus |= Monitor2Sense ;
+                if ( OutputSelect & SetSCARTOutput )
+                {
+                    bConnectStatus ^= ( Monitor2Sense | SCARTSense ) ;
+                }
+            }
+        }
+        if ( XGI_Is301C( pVBInfo ) )   /* 301C only */
+            XGINew_SetRegOR( pVBInfo->Part4Port , 0x0D , 0x04 ) ;      /* Set Part4 0x0D D[2]=1 for dynamic sense */
+
+        if ( ( XGINew_Is301B( pVBInfo ) ) )
+            XGINew_SetRegOR( pVBInfo->Part2Port , 0x00 , 0x0C ) ;    /* ????????? */
+
+       if ( XGINew_SenseHiTV( HwDeviceExtension , pVBInfo) )           /* add by kuku for Dysense HiTV //start */
+       {
+           bConnectStatus|= YPbPrSense ;
+       }
+       else
+       {
+        tempbx = XGI330_YCSenseData2 ; /* Y/C Sense Data Ptr */
+        tempcx = 0x0604 ;
+        if ( XGINew_Sense( tempbx , tempcx , pVBInfo) )
+            bConnectStatus |= SVIDEOSense ;
+
+        if ( OutputSelect & BoardTVType )
+        {
+            tempbx = XGI330_VideoSenseData2 ;
+            tempcx = 0x0804 ;
+            if ( XGINew_Sense(tempbx , tempcx, pVBInfo) )
+                bConnectStatus|= AVIDEOSense ;
+        }
+        else
+        {
+            if ( !( bConnectStatus & SVIDEOSense ) )
+            {
+                tempbx = XGI330_VideoSenseData2 ;
+                tempcx = 0x0804 ;
+                if ( XGINew_Sense( tempbx , tempcx, pVBInfo ) )
+                    bConnectStatus |= AVIDEOSense ;
+            }
+        }
+       } /* end */
+        /* DySenseVBCnt */
+
+        tempbx = 0 ;
+        tempcx = 0 ;
+        XGINew_Sense(tempbx , tempcx, pVBInfo ) ;
+
+        if ( !( bConnectStatus & Monitor2Sense ) )
+        {
+            if ( XGI_SenseLCD( pHWDE , pVBInfo ) )
+                bConnectStatus |= LCDSense ;
+        }
+
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~( AVIDEOSense | SVIDEOSense | LCDSense | Monitor2Sense | Monitor1Sense ) , bConnectStatus ) ;
+
+        XGINew_SetReg1( pVBInfo->Part4Port , 0x0D , pre_Part4_D ) ;
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , pre_Part2_0 ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x1E , pre_SR1E ) ;
+
+        if ( XGI_Is301C( pVBInfo ) )   /* 301C only */
+        {
+            tempax = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
+            if ( tempax & 0x20 )
+            {
+                /* Reset VBPro */
+                for( tempcx = 2 ; tempcx > 0 ; tempcx-- )
+                {
+                    tempax ^= 0x20 ;
+                    XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , tempax ) ;
+                }
+            }
+        }
+        /* End of dynamic sense VB */
+    }
+    else
+    {
+        XGI_SenseCRT1(pVBInfo) ;
+        XGI_GetSenseStatus( HwDeviceExtension, pVBInfo ) ;     /* sense CRT2 */
+        bConnectStatus = XGINew_GetReg1( pVBInfo->P3d4 , 0x32 ) ;
+    }
+    temp = pushax & 0x00FF ;           /* 0512 Fix Dysense hanged */
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x17 , temp ) ;
+    if ( bConnectStatus )
+    {
+        *ujConnectStatus = bConnectStatus ;
+        return( 1 ) ;
+    }
+    else
+        return( 0 ) ;
+}
+
+#endif /* WIN2000 */
+
+/* --------------------------------------------------------------------- */
+/* Function : XGISetDPMS */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+VOID XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE )
+{
+    USHORT ModeNo, ModeIdIndex ;
+    UCHAR  temp ;
+    VB_DEVICE_INFO VBINF;
+    PVB_DEVICE_INFO pVBInfo = &VBINF;
+    pVBInfo->BaseAddr = (ULONG)pXGIHWDE->pjIOAddress ;
+    pVBInfo->ROMAddr  = pXGIHWDE->pjVirtualRomBase ;
+
+
+    pVBInfo->IF_DEF_LVDS = 0 ;
+    pVBInfo->IF_DEF_CH7005 = 0 ;
+    pVBInfo->IF_DEF_HiVision = 1 ;
+    pVBInfo->IF_DEF_LCDA = 1 ;
+    pVBInfo->IF_DEF_CH7017 = 0 ;
+    pVBInfo->IF_DEF_YPbPr = 1 ;
+    pVBInfo->IF_DEF_CRT2Monitor = 0 ;
+    pVBInfo->IF_DEF_VideoCapture = 0 ;
+    pVBInfo->IF_DEF_ScaleLCD = 0 ;
+    pVBInfo->IF_DEF_OEMUtil = 0 ;
+    pVBInfo->IF_DEF_PWD = 0 ;
+
+    InitTo330Pointer( pXGIHWDE->jChipType,  pVBInfo ) ;
+    ReadVBIOSTablData( pXGIHWDE->jChipType , pVBInfo) ;
+
+    pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+    pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+    pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+    pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+    pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+    pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+    pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+    pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+    pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+    pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+    pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+    pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+    pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+    pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+    pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+    pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+    pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+    if ( pXGIHWDE->jChipType == XG27 )
+    {
+        if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 )
+        {
+          if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) & 0x20 )
+          {
+            pVBInfo->IF_DEF_LVDS = 1 ;
+          }
+        }
+    }
+
+    if ( pVBInfo->IF_DEF_CH7007 == 0 )
+    {
+        XGINew_SetModeScratch ( pXGIHWDE , pVBInfo ) ;
+    }
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;    /* 1.Openkey */
+    XGI_UnLockCRT2( pXGIHWDE , pVBInfo) ;
+    ModeNo = XGINew_GetReg1( pVBInfo->P3d4 , 0x34 ) ;
+    XGI_SearchModeID( ModeNo , &ModeIdIndex, pVBInfo ) ;
+    XGI_GetVGAType( pXGIHWDE , pVBInfo ) ;
+
+    if ( ( pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) || ( pVBInfo->IF_DEF_CH7007 == 1 ))
+    {
+        XGI_GetVBType( pVBInfo ) ;
+        XGI_GetVBInfo( ModeNo , ModeIdIndex , pXGIHWDE, pVBInfo ) ;
+        XGI_GetTVInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+        XGI_GetLCDInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+    }
+
+    if ( VESA_POWER_STATE == 0x00000400 )
+      XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , ( UCHAR )( XGINew_GetReg1( pVBInfo->Part4Port , 0x31 ) & 0xFE ) ) ;
+    else
+      XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , ( UCHAR )( XGINew_GetReg1( pVBInfo->Part4Port , 0x31 ) | 0x01 ) ) ;
+
+    temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x1f ) ;
+    temp &= 0x3f ;
+    switch ( VESA_POWER_STATE )
+    {
+        case 0x00000000: /* on */
+            if ( ( pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) )
+            {
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x00 ) ) ;
+                XGI_EnableBridge( pXGIHWDE, pVBInfo ) ;
+            }
+            else
+            {
+               if ( pXGIHWDE->jChipType == XG21 )
+               {
+                 if ( pVBInfo->IF_DEF_LVDS == 1 )
+                 {
+                   XGI_XG21BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
+                   XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
+                 }
+               }
+               if ( pXGIHWDE->jChipType == XG27 )
+               {
+                 if ( pVBInfo->IF_DEF_LVDS == 1 )
+                 {
+                   XGI_XG27BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
+                   XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
+                 }
+               }
+               XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , ~0xC0 , 0x00 ) ;
+               XGINew_SetRegAND( pVBInfo->P3c4 , 0x01 , ~0x20 ) ;              /* CRT on */
+
+               if ( pXGIHWDE->jChipType == XG21 )
+               {
+                 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+                 if ( temp & 0xE0 )
+                 {
+                   XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ; /* DVO ON */
+                   XGI_SetXG21FPBits( pVBInfo );
+                   XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ;          /* Enable write GPIOF */
+                   /*XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~0x20 , 0x20 ) ;*/     /* LCD Display ON */
+                 }
+                 XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
+                 XGI_DisplayOn( pXGIHWDE, pVBInfo );
+               }
+               if ( pXGIHWDE->jChipType == XG27 )
+               {
+                 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+                 if ( temp & 0xE0 )
+                 {
+                   XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ; /* DVO ON */
+                   XGI_SetXG27FPBits( pVBInfo );
+                   XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ;          /* Enable write GPIOF */
+                   /*XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~0x20 , 0x20 ) ;*/     /* LCD Display ON */
+                 }
+                 XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
+                 XGI_DisplayOn( pXGIHWDE, pVBInfo );
+               }
+            }
+            break ;
+        case 0x00000100: /* standby */
+            if ( pXGIHWDE->jChipType >= XG21 )
+            {
+                XGI_DisplayOff( pXGIHWDE, pVBInfo );
+            }
+
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x40 ) ) ;
+            break ;
+        case 0x00000200: /* suspend */
+            if ( pXGIHWDE->jChipType == XG21 )
+            {
+                XGI_DisplayOff( pXGIHWDE, pVBInfo );
+                XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
+            }
+            if ( pXGIHWDE->jChipType == XG27 )
+            {
+                XGI_DisplayOff( pXGIHWDE, pVBInfo );
+                XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
+            }
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x80 ) ) ;
+            break ;
+        case 0x00000400: /* off */
+            if ( (pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) )
+            {
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0xc0 ) ) ;
+                XGI_DisableBridge( pXGIHWDE, pVBInfo ) ;
+            }
+            else
+            {
+               if ( pXGIHWDE->jChipType == XG21 )
+               {
+                 XGI_DisplayOff( pXGIHWDE, pVBInfo );
+
+                 XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
+
+                 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+                 if ( temp & 0xE0 )
+                 {
+                   XGINew_SetRegAND( pVBInfo->P3c4 , 0x09 , ~0x80 ) ;          /* DVO Off */
+                   XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ;          /* Enable write GPIOF */
+                   /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x48 , ~0x20 ) ;*/              /* LCD Display OFF */
+                 }
+               }
+               if ( pXGIHWDE->jChipType == XG27 )
+               {
+                 XGI_DisplayOff( pXGIHWDE, pVBInfo );
+
+                 XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
+
+                 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+                 if ( temp & 0xE0 )
+                 {
+                   XGINew_SetRegAND( pVBInfo->P3c4 , 0x09 , ~0x80 ) ;          /* DVO Off */
+                 }
+               }
+               XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , ~0xC0 , 0xC0 ) ;
+               XGINew_SetRegOR( pVBInfo->P3c4 , 0x01 , 0x20 ) ;                /* CRT Off */
+
+               if ( ( pXGIHWDE->jChipType == XG21 ) && ( pVBInfo->IF_DEF_LVDS == 1 ) )
+               {
+                 XGI_XG21SetPanelDelay( 4,pVBInfo ) ;
+                 XGI_XG21BLSignalVDD( 0x01 , 0x00, pVBInfo ) ; /* LVDS VDD off */
+                 XGI_XG21SetPanelDelay( 5,pVBInfo ) ;
+               }
+               if ( ( pXGIHWDE->jChipType == XG27 ) && ( pVBInfo->IF_DEF_LVDS == 1 ) )
+               {
+                 XGI_XG21SetPanelDelay( 4,pVBInfo ) ;
+                 XGI_XG27BLSignalVDD( 0x01 , 0x00, pVBInfo ) ; /* LVDS VDD off */
+                 XGI_XG21SetPanelDelay( 5,pVBInfo ) ;
+               }
+            }
+            break ;
+
+        default:
+            break ;
+    }
+    XGI_LockCRT2( pXGIHWDE , pVBInfo ) ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetSenseStatus */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempax = 0 , tempbx , tempcx , temp ,
+           P2reg0 = 0 , SenseModeNo = 0 , OutputSelect = *pVBInfo->pOutputSelect ,
+           ModeIdIndex , i ;
+    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+
+    if ( pVBInfo->IF_DEF_LVDS == 1 )
+    {
+        tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ;      /* ynlai 02/27/2002 */
+        tempbx = XGINew_GetReg1( pVBInfo->P3c4 , 0x1B ) ;
+        tempax = ( ( tempax & 0xFE ) >> 1 ) | ( tempbx << 8 ) ;
+        if ( tempax == 0x00 )
+        {              /* Get Panel id from DDC */
+            temp = XGINew_GetLCDDDCInfo( HwDeviceExtension, pVBInfo ) ;
+            if ( temp == 1 )
+            {          /* LCD connect */
+                XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x39 , 0xFF , 0x01 ) ;     /* set CR39 bit0="1" */
+                XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , 0xEF , 0x00 ) ;     /* clean CR37 bit4="0" */
+                temp = LCDSense ;
+            }
+            else
+            {          /* LCD don't connect */
+                temp = 0 ;
+            }
+        }
+        else
+        {
+            XGINew_GetPanelID(pVBInfo) ;
+            temp = LCDSense ;
+        }
+
+        tempbx = ~( LCDSense | AVIDEOSense | SVIDEOSense ) ;
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , tempbx , temp ) ;
+    }
+    else
+    {          /* for 301 */
+        if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+        {      /* for HiVision */
+            tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x38 ) ;
+            temp = tempax & 0x01 ;
+            tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) ;
+            temp = temp | ( tempax & 0x02 ) ;
+            XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xA0 , temp ) ;
+        }
+        else
+        {
+            if ( XGI_BridgeIsOn( pVBInfo ) )
+            {
+                P2reg0 = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
+                if ( !XGINew_BridgeIsEnable( HwDeviceExtension, pVBInfo ) )
+                {
+                    SenseModeNo = 0x2e ;
+                    /* XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x41 ) ; */
+                    /* XGISetModeNew( HwDeviceExtension , 0x2e ) ; // ynlai InitMode */
+
+                    temp = XGI_SearchModeID( SenseModeNo , &ModeIdIndex, pVBInfo ) ;
+                    XGI_GetVGAType( HwDeviceExtension , pVBInfo) ;
+                    XGI_GetVBType( pVBInfo ) ;
+                    pVBInfo->SetFlag = 0x00 ;
+                    pVBInfo->ModeType = ModeVGA ;
+                    pVBInfo->VBInfo = SetCRT2ToRAMDAC | LoadDACFlag | SetInSlaveMode ;
+                    XGI_GetLCDInfo( 0x2e , ModeIdIndex, pVBInfo ) ;
+                    XGI_GetTVInfo(  0x2e , ModeIdIndex, pVBInfo ) ;
+                    XGI_EnableBridge( HwDeviceExtension, pVBInfo ) ;
+                    XGI_SetCRT2Group301( SenseModeNo , HwDeviceExtension, pVBInfo ) ;
+                    XGI_SetCRT2ModeRegs( 0x2e , HwDeviceExtension, pVBInfo ) ;
+                    /* XGI_DisableBridge( HwDeviceExtension, pVBInfo ) ; */
+                    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xDF , 0x20 ) ; /* Display Off 0212 */
+                    for( i = 0 ; i < 20 ; i++ )
+                    {
+                        XGI_LongWait(pVBInfo) ;
+                    }
+                }
+                XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , 0x1c ) ;
+                tempax = 0 ;
+                tempbx = *pVBInfo->pRGBSenseData ;
+
+                if ( !( XGINew_Is301B( pVBInfo ) ) )
+                {
+                    tempbx = *pVBInfo->pRGBSenseData2 ;
+                }
+
+                tempcx = 0x0E08 ;
+                if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+                {
+                    if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+                    {
+                        tempax |= Monitor2Sense ;
+                    }
+                }
+
+                if ( pVBInfo->VBType & VB_XGI301C)
+                {
+                    XGINew_SetRegOR( pVBInfo->Part4Port , 0x0d , 0x04 ) ;
+                }
+
+               if ( XGINew_SenseHiTV( HwDeviceExtension , pVBInfo) )           /* add by kuku for Multi-adapter sense HiTV */
+               {
+                   tempax |= HiTVSense ;
+                    if ( ( pVBInfo->VBType & VB_XGI301C ) )
+                    {
+                       tempax ^= ( HiTVSense | YPbPrSense ) ;
+                    }
+                }
+
+               if ( !( tempax & ( HiTVSense | YPbPrSense ) ) )         /* start */
+                {
+
+                    tempbx = *pVBInfo->pYCSenseData ;
+
+                    if ( !( XGINew_Is301B(  pVBInfo ) ) )
+                    {
+                      tempbx=*pVBInfo->pYCSenseData2;
+                    }
+
+                    tempcx = 0x0604 ;
+                    if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+                    {
+                      if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+                      {
+                          tempax |= SVIDEOSense ;
+                      }
+                    }
+
+                    if ( OutputSelect & BoardTVType )
+                    {
+                      tempbx = *pVBInfo->pVideoSenseData ;
+
+                      if ( !( XGINew_Is301B( pVBInfo ) ) )
+                      {
+                          tempbx = *pVBInfo->pVideoSenseData2 ;
+                      }
+
+                      tempcx = 0x0804 ;
+                      if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+                      {
+                          if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+                          {
+                              tempax |= AVIDEOSense ;
+                          }
+                      }
+                    }
+                    else
+                    {
+                      if ( !( tempax & SVIDEOSense ) )
+                      {
+                        tempbx = *pVBInfo->pVideoSenseData ;
+
+                        if ( !( XGINew_Is301B( pVBInfo ) ) )
+                        {
+                            tempbx=*pVBInfo->pVideoSenseData2;
+                        }
+
+                        tempcx = 0x0804 ;
+                        if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+                        {
+                            if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+                            {
+                                tempax |= AVIDEOSense ;
+                            }
+                        }
+                      }
+                    }
+                }
+           } /* end */
+            if ( !( tempax & Monitor2Sense ) )
+            {
+                if ( XGINew_SenseLCD( HwDeviceExtension, pVBInfo ) )
+                {
+                    tempax |= LCDSense ;
+                }
+            }
+            tempbx = 0 ;
+            tempcx = 0 ;
+            XGINew_Sense(tempbx , tempcx, pVBInfo ) ;
+
+            XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~0xDF , tempax ) ;
+            XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , P2reg0 ) ;
+
+            if ( !( P2reg0 & 0x20 ) )
+            {
+                pVBInfo->VBInfo = DisableCRT2Display ;
+                /* XGI_SetCRT2Group301( SenseModeNo , HwDeviceExtension, pVBInfo ) ; */
+            }
+        }
+    }
+    XGI_DisableBridge( HwDeviceExtension, pVBInfo ) ;          /* shampoo 0226 */
+
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SenseLCD */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGINew_SenseLCD( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
+{
+    /* USHORT SoftSetting ; */
+    USHORT temp ;
+
+    if ( ( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40 ) )
+        temp = 0 ;
+    else
+        temp=XGINew_GetPanelID(pVBInfo) ;
+
+    if( !temp )
+        temp = XGINew_GetLCDDDCInfo( HwDeviceExtension, pVBInfo ) ;
+
+    return( temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_GetLCDDDCInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_GetLCDDDCInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT temp ;
+
+    /* add lcd sense */
+    if ( HwDeviceExtension->ulCRT2LCDType == LCD_UNKNOWN )
+    {
+        return( 0 ) ;
+    }
+    else
+    {
+        temp = ( USHORT )HwDeviceExtension->ulCRT2LCDType ;
+        switch( HwDeviceExtension->ulCRT2LCDType )
+        {
+            case LCD_INVALID:
+            case LCD_800x600:
+            case LCD_1024x768:
+            case LCD_1280x1024:
+                break ;
+
+            case LCD_640x480:
+            case LCD_1024x600:
+            case LCD_1152x864:
+            case LCD_1280x960:
+            case LCD_1152x768:
+                temp = 0 ;
+                break ;
+
+            case LCD_1400x1050:
+            case LCD_1280x768:
+            case LCD_1600x1200:
+                break ;
+
+            case LCD_1920x1440:
+            case LCD_2048x1536:
+                temp = 0 ;
+                break ;
+
+            default:
+                break ;
+        }
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , 0xF0 , temp ) ;
+        return( 1 ) ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT PanelTypeTable[ 16 ] = { SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType00 ,
+                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType01 ,
+                                    SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType02 ,
+                                    SyncNN | PanelRGB18Bit | Panel640x480  | _PanelType03 ,
+                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType04 ,
+                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType05 ,
+                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType06 ,
+                                    SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType07 ,
+                                    SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType08 ,
+                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType09 ,
+                                    SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType0A ,
+                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0B ,
+                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0C ,
+                                    SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType0D ,
+                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0E ,
+                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0F } ;
+    USHORT tempax , tempbx , temp ;
+    /* USHORT return_flag ; */
+
+    tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ;
+    tempbx = tempax & 0x1E ;
+
+    if ( tempax == 0 )
+        return( 0 ) ;
+    else
+    {
+/*
+        if ( !( tempax & 0x10 ) )
+        {
+            if ( pVBInfo->IF_DEF_LVDS == 1 )
+            {
+                tempbx = 0 ;
+                temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x38 ) ;
+                if ( temp & 0x40 )
+                    tempbx |= 0x08 ;
+                if ( temp & 0x20 )
+                    tempbx |= 0x02 ;
+                if ( temp & 0x01 )
+                    tempbx |= 0x01 ;
+
+                temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) ;
+                if ( temp & 0x80 )
+                    tempbx |= 0x04 ;
+            }
+            else
+            {
+                return( 0 ) ;
+            }
+        }
+*/
+
+        tempbx = tempbx >> 1 ;
+        temp = tempbx & 0x00F ;
+        XGINew_SetReg1( pVBInfo->P3d4 , 0x36 , temp ) ;
+        tempbx-- ;
+        tempbx = PanelTypeTable[ tempbx ] ;
+
+        temp = ( tempbx & 0xFF00 ) >> 8 ;
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~( LCDSyncBit | LCDRGB18Bit ) , temp ) ;
+        return( 1 ) ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_BridgeIsEnable */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_BridgeIsEnable( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT flag ;
+
+    if ( XGI_BridgeIsOn( pVBInfo ) == 0 )
+    {
+        flag = XGINew_GetReg1( pVBInfo->Part1Port , 0x0 ) ;
+
+        if ( flag & 0x050 )
+        {
+            return( 1 ) ;
+        }
+        else
+        {
+            return( 0 ) ;
+        }
+
+    }
+    return( 0 ) ;
+}
+
+/* ------------------------------------------------------ */
+/* Function : XGINew_SenseHiTV */
+/* Input : */
+/* Output : */
+/* Description : */
+/* ------------------------------------------------------ */
+BOOLEAN XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempbx , tempcx , temp , i , tempch;
+
+    tempbx = *pVBInfo->pYCSenseData2 ;
+
+    tempcx = 0x0604 ;
+
+    temp = tempbx & 0xFF ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
+    temp = ( tempbx & 0xFF00 ) >> 8 ;
+    temp |= ( tempcx & 0x00FF ) ;
+    XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
+
+    for( i = 0 ; i < 10 ; i++ )
+        XGI_LongWait(pVBInfo) ;
+
+    tempch = ( tempcx & 0xFF00 ) >> 8;
+    temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
+    temp = temp ^ ( 0x0E ) ;
+    temp &= tempch ;
+
+    if ( temp !=  tempch )
+        return( 0 ) ;
+
+    tempbx = *pVBInfo->pVideoSenseData2 ;
+
+    tempcx = 0x0804 ;
+    temp = tempbx & 0xFF ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
+    temp = ( tempbx & 0xFF00 ) >> 8 ;
+    temp |= ( tempcx & 0x00FF ) ;
+    XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
+
+    for( i = 0 ; i < 10 ; i++ )
+        XGI_LongWait(pVBInfo) ;
+
+    tempch = ( tempcx & 0xFF00 ) >> 8;
+    temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
+    temp = temp ^ ( 0x0E ) ;
+    temp &= tempch ;
+
+    if ( temp !=  tempch )
+        return( 0 ) ;
+    else
+    {
+      tempbx = 0x3FF ;
+      tempcx = 0x0804 ;
+      temp = tempbx & 0xFF ;
+      XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
+      temp = ( tempbx & 0xFF00 ) >> 8 ;
+      temp |= ( tempcx & 0x00FF ) ;
+      XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
+
+      for( i = 0 ; i < 10 ; i++ )
+          XGI_LongWait(pVBInfo) ;
+
+      tempch = ( tempcx & 0xFF00 ) >> 8;
+      temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
+      temp = temp ^ ( 0x0E ) ;
+      temp &= tempch ;
+
+      if ( temp != tempch )
+          return( 1 ) ;
+      else
+         return( 0 ) ;
+    }
+}
+
+
+
+/*
+;-----------------------------------------------------------------------------
+;       Description: Get Panel support
+;      O/P        :
+;            BL: Panel ID=81h for no scaler LVDS
+;                   BH: Panel enhanced Mode Count
+;                   CX: Panel H. resolution
+;                   DX: PAnel V. resolution
+;-----------------------------------------------------------------------------
+*/
+void XGI_XG21Fun14Sub70( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+{
+
+    USHORT ModeIdIndex;
+    USHORT ModeNo;
+
+    USHORT EModeCount;
+    USHORT lvdstableindex;
+
+    lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+    pBiosArguments->h.bl = 0x81;
+    pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE;
+    pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE;
+    EModeCount = 0;
+
+    pBiosArguments->x.ax = 0x0014;
+    for( ModeIdIndex = 0 ; ;  ModeIdIndex ++ )
+    {
+        ModeNo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID;
+        if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID == 0xFF )
+        {
+            pBiosArguments->h.bh = (UCHAR) EModeCount;
+            return;
+        }
+        if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) )
+        {
+          continue;
+        }
+        EModeCount++ ;
+    }
+}
+/*(
+;-----------------------------------------------------------------------------
+;
+;       Description: Get Panel mode ID for enhanced mode
+;      I/P        : BH: EModeIndex ( which < Panel enhanced Mode Count )
+;      O/P        :
+;            BL: Mode ID
+;                   CX: H. resolution of the assigned by the index
+;                   DX: V. resolution of the assigned by the index
+;
+;-----------------------------------------------------------------------------
+*/
+void XGI_XG21Fun14Sub71( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+{
+
+    USHORT EModeCount;
+    USHORT ModeIdIndex,resindex;
+    USHORT ModeNo;
+    USHORT EModeIndex = pBiosArguments->h.bh;
+
+    EModeCount = 0;
+    for( ModeIdIndex = 0 ; ;  ModeIdIndex ++ )
+    {
+        ModeNo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID;
+        if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID == 0xFF )
+        {
+            pBiosArguments->x.ax = 0x0114;
+            return;
+        }
+        if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) )
+        {
+          continue;
+        }
+        if (EModeCount == EModeIndex)
+        {
+            resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+            pBiosArguments->h.bl = (UCHAR) ModeNo;
+            pBiosArguments->x.cx = pVBInfo->ModeResInfo[ resindex ].HTotal ;                     /* xres->ax */
+            pBiosArguments->x.dx = pVBInfo->ModeResInfo[ resindex ].VTotal ;                     /* yres->bx */
+            pBiosArguments->x.ax = 0x0014;
+        }
+        EModeCount++ ;
+
+    }
+
+}
+/*
+;-----------------------------------------------------------------------------
+;
+;       Description: Validate Panel modes ID support
+;      I/P        :
+;            BL: ModeID
+;      O/P        :
+;                   CX: H. resolution of the assigned by the index
+;                   DX: V. resolution of the assigned by the index
+;
+;-----------------------------------------------------------------------------
+*/
+void XGI_XG21Fun14Sub72( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+{
+    USHORT ModeIdIndex,resindex;
+    USHORT ModeNo;
+
+
+    ModeNo = pBiosArguments->h.bl ;
+    XGI_SearchModeID( ModeNo, &ModeIdIndex, pVBInfo);
+    if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) )
+    {
+        pBiosArguments->x.cx = 0;
+        pBiosArguments->x.dx = 0;
+        pBiosArguments->x.ax = 0x0114;
+        return;
+    }
+    resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+    if ( ModeNo <= 0x13 )
+    {
+        pBiosArguments->x.cx = pVBInfo->StResInfo[ resindex ].HTotal ;
+        pBiosArguments->x.dx = pVBInfo->StResInfo[ resindex ].VTotal ;
+    }
+    else
+    {
+        pBiosArguments->x.cx = pVBInfo->ModeResInfo[ resindex ].HTotal ;                         /* xres->ax */
+        pBiosArguments->x.dx = pVBInfo->ModeResInfo[ resindex ].VTotal ;                         /* yres->bx */
+    }
+
+    pBiosArguments->x.ax = 0x0014;
+
+}
+
+/*
+;-----------------------------------------------------------------------------
+;      Description: Get Customized Panel misc. information support
+;      I/P        : Select
+;                   to get panel horizontal timing
+;                       to get panel vertical timing
+;                       to get channel clock parameter
+;            to get panel misc information
+;
+;      O/P        :
+;                   BL: for input Select = 0 ;
+;                       BX: *Value1 = Horizontal total
+;                       CX: *Value2 = Horizontal front porch
+;                       DX: *Value2 = Horizontal sync width
+;                   BL: for input Select = 1 ;
+;                       BX: *Value1 = Vertical total
+;                       CX: *Value2 = Vertical front porch
+;                       DX: *Value2 = Vertical sync width
+;            BL: for input Select = 2 ;
+;                       BX: Value1 = The first CLK parameter
+;                       CX: Value2 = The second CLK parameter
+;                   BL: for input Select = 4 ;
+;                       BX[15]: *Value1 D[15] VESA V. Polarity
+;                       BX[14]: *Value1 D[14] VESA H. Polarity
+;                       BX[7]: *Value1 D[7] Panel V. Polarity
+;                       BX[6]: *Value1 D[6] Panel H. Polarity
+;-----------------------------------------------------------------------------
+*/
+void XGI_XG21Fun14Sub73( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+{
+    UCHAR Select;
+
+    USHORT lvdstableindex;
+
+    lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+    Select = pBiosArguments->h.bl;
+
+    switch (Select)
+    {
+        case 0:
+                pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
+                pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP;
+                pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC;
+                break;
+        case 1:
+                pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
+                pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP;
+                pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC;
+                break;
+        case 2:
+                pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1;
+                pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2;
+                break;
+        case 4:
+                pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability;
+                break;
+    }
+
+    pBiosArguments->x.ax = 0x0014;
+}
+
+
+void XGI_XG21Fun14( PXGI_HW_DEVICE_INFO pXGIHWDE, PX86_REGS pBiosArguments)
+{
+    VB_DEVICE_INFO VBINF;
+    PVB_DEVICE_INFO pVBInfo = &VBINF;
+
+    pVBInfo->IF_DEF_LVDS = 0 ;
+    pVBInfo->IF_DEF_CH7005 = 0 ;
+    pVBInfo->IF_DEF_HiVision = 1 ;
+    pVBInfo->IF_DEF_LCDA = 1 ;
+    pVBInfo->IF_DEF_CH7017 = 0 ;
+    pVBInfo->IF_DEF_YPbPr = 1 ;
+    pVBInfo->IF_DEF_CRT2Monitor = 0 ;
+    pVBInfo->IF_DEF_VideoCapture = 0 ;
+    pVBInfo->IF_DEF_ScaleLCD = 0 ;
+    pVBInfo->IF_DEF_OEMUtil = 0 ;
+    pVBInfo->IF_DEF_PWD = 0 ;
+
+    InitTo330Pointer( pXGIHWDE->jChipType,  pVBInfo ) ;
+    ReadVBIOSTablData( pXGIHWDE->jChipType , pVBInfo) ;
+
+    pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+    pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+    pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+    pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+    pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+    pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+    pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+    pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+    pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+    pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+    pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+    pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+    pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+    pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+    pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+    pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+    pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+    switch(pBiosArguments->x.ax)
+    {
+    case 0x1470:
+         XGI_XG21Fun14Sub70( pVBInfo , pBiosArguments ) ;
+         break;
+    case 0x1471:
+         XGI_XG21Fun14Sub71( pVBInfo , pBiosArguments ) ;
+         break;
+    case 0x1472:
+         XGI_XG21Fun14Sub72( pVBInfo , pBiosArguments ) ;
+         break;
+    case 0x1473:
+         XGI_XG21Fun14Sub73( pVBInfo , pBiosArguments ) ;
+         break;
+    }
+}
diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h
new file mode 100644 (file)
index 0000000..9a72f5e
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef  _VBEXT_
+#define  _VBEXT_
+
+struct DWORDREGS {
+    ULONG    Eax, Ebx, Ecx, Edx, Esi, Edi, Ebp;
+};
+
+struct WORDREGS {
+    USHORT    ax, hi_ax, bx, hi_bx, cx, hi_cx, dx, hi_dx, si, hi_si, di ,hi_di, bp, hi_bp;
+};
+
+struct BYTEREGS {
+    UCHAR   al, ah, hi_al, hi_ah, bl, bh, hi_bl, hi_bh, cl, ch, hi_cl, hi_ch, dl, dh, hi_dl, hi_dh;
+};
+
+typedef union   _X86_REGS    {
+    struct  DWORDREGS e;
+    struct  WORDREGS x;
+    struct  BYTEREGS h;
+} X86_REGS, *PX86_REGS;
+
+extern   void     XGI_XG21Fun14( PXGI_HW_DEVICE_INFO pXGIHWDE, PX86_REGS pBiosArguments);
+extern   void     XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE ) ;
+extern   void     XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
+extern   void     XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+extern   void    ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
+extern   USHORT   XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo);
+#ifdef WIN2000
+extern   BOOLEAN  XGI_DySense( PHW_DEVICE_EXTENSION pHWDE , PUCHAR ujConnectStatus );
+#endif /* WIN2000 */
+
+#endif
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
new file mode 100644 (file)
index 0000000..b85ca9b
--- /dev/null
@@ -0,0 +1,3444 @@
+#include "osdef.h"
+#include "vgatypes.h"
+
+
+#ifdef LINUX_KERNEL
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/delay.h> /* udelay */
+#include "XGIfb.h"
+/*#if LINUX_VERSxION_CODE >= KERNEL_VERSION(2,5,0)
+#include <video/XGIfb.h>
+#else
+#include <linux/XGIfb.h>
+#endif */
+#endif
+
+#ifdef WIN2000
+#include <dderror.h>
+#include <devioctl.h>
+#include <miniport.h>
+#include <ntddvdeo.h>
+#include <video.h>
+#include "xgiv.h"
+#include "dd_i2c.h"
+#include "tools.h"
+#endif
+
+#include "vb_def.h"
+#include "vb_struct.h"
+#include "vb_util.h"
+#include "vb_setmode.h"
+#include "vb_init.h"
+#include "vb_ext.h"
+
+#ifdef LINUX_XF86
+#include "xf86.h"
+#include "xf86PciInfo.h"
+#include "xgi.h"
+#include "xgi_regs.h"
+#endif
+
+#ifdef LINUX_KERNEL
+#include <asm/io.h>
+#include <linux/types.h>
+#endif
+
+
+
+
+UCHAR    XGINew_ChannelAB,XGINew_DataBusWidth;
+
+USHORT XGINew_DRAMType[17][5]={{0x0C,0x0A,0x02,0x40,0x39},{0x0D,0x0A,0x01,0x40,0x48},
+                     {0x0C,0x09,0x02,0x20,0x35},{0x0D,0x09,0x01,0x20,0x44},
+                     {0x0C,0x08,0x02,0x10,0x31},{0x0D,0x08,0x01,0x10,0x40},
+                     {0x0C,0x0A,0x01,0x20,0x34},{0x0C,0x09,0x01,0x08,0x32},
+                     {0x0B,0x08,0x02,0x08,0x21},{0x0C,0x08,0x01,0x08,0x30},
+                     {0x0A,0x08,0x02,0x04,0x11},{0x0B,0x0A,0x01,0x10,0x28},
+                     {0x09,0x08,0x02,0x02,0x01},{0x0B,0x09,0x01,0x08,0x24},
+                     {0x0B,0x08,0x01,0x04,0x20},{0x0A,0x08,0x01,0x02,0x10},
+                     {0x09,0x08,0x01,0x01,0x00}};
+
+USHORT XGINew_SDRDRAM_TYPE[13][5]=
+{
+{ 2,12, 9,64,0x35},
+{ 1,13, 9,64,0x44},
+{ 2,12, 8,32,0x31},
+{ 2,11, 9,32,0x25},
+{ 1,12, 9,32,0x34},
+{ 1,13, 8,32,0x40},
+{ 2,11, 8,16,0x21},
+{ 1,12, 8,16,0x30},
+{ 1,11, 9,16,0x24},
+{ 1,11, 8, 8,0x20},
+{ 2, 9, 8, 4,0x01},
+{ 1,10, 8, 4,0x10},
+{ 1, 9, 8, 2,0x00}
+};
+
+USHORT XGINew_DDRDRAM_TYPE[4][5]=
+{
+{ 2,12, 9,64,0x35},
+{ 2,12, 8,32,0x31},
+{ 2,11, 8,16,0x21},
+{ 2, 9, 8, 4,0x01}
+};
+USHORT XGINew_DDRDRAM_TYPE340[4][5]=
+{
+{ 2,13, 9,64,0x45},
+{ 2,12, 9,32,0x35},
+{ 2,12, 8,16,0x31},
+{ 2,11, 8, 8,0x21}
+};
+USHORT XGINew_DDRDRAM_TYPE20[12][5]=
+{
+{ 2,14,11,128,0x5D},
+{ 2,14,10,64,0x59},
+{ 2,13,11,64,0x4D},
+{ 2,14, 9,32,0x55},
+{ 2,13,10,32,0x49},
+{ 2,12,11,32,0x3D},
+{ 2,14, 8,16,0x51},
+{ 2,13, 9,16,0x45},
+{ 2,12,10,16,0x39},
+{ 2,13, 8, 8,0x41},
+{ 2,12, 9, 8,0x35},
+{ 2,12, 8, 4,0x31}
+};
+
+void     XGINew_SetDRAMSize_340(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+void     XGINew_SetDRAMSize_310(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+void     XGINew_SetMemoryClock(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+void     XGINew_SetDRAMModeRegister(PVB_DEVICE_INFO );
+void     XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+void    XGINew_SetDRAMDefaultRegister340(PXGI_HW_DEVICE_INFO HwDeviceExtension, ULONG, PVB_DEVICE_INFO );
+UCHAR    XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension) ;
+
+int      XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+void     XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO ,PVB_DEVICE_INFO) ;
+void     XGINew_CheckBusWidth_310( PVB_DEVICE_INFO) ;
+int      XGINew_SDRSizing(PVB_DEVICE_INFO);
+int      XGINew_DDRSizing( PVB_DEVICE_INFO );
+void     XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+int      XGINew_RAMType;                  /*int      ModeIDOffset,StandTable,CRT1Table,ScreenOffset,REFIndex;*/
+ULONG   UNIROM;                          /* UNIROM */
+BOOLEAN  ChkLFB( PVB_DEVICE_INFO );
+void     XGINew_Delay15us(ULONG);
+void     SetPowerConsume (PXGI_HW_DEVICE_INFO HwDeviceExtension,ULONG XGI_P3d4Port);
+void    ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
+void    XGINew_DDR1x_MRS_XG20( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo);
+void     XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+void     XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+void    XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+void     XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+void     XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+UCHAR    GetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+void     XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+UCHAR    GetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+
+#ifdef WIN2000
+/* [Billy] 2007/05/20 For CH7007 */
+extern  UCHAR CH7007TVReg_UNTSC[][8],CH7007TVReg_ONTSC[][8],CH7007TVReg_UPAL[][8],CH7007TVReg_OPAL[][8];
+extern  UCHAR XGI7007_CHTVVCLKUNTSC[],XGI7007_CHTVVCLKONTSC[],XGI7007_CHTVVCLKUPAL[],XGI7007_CHTVVCLKOPAL[];
+#endif
+
+#ifdef LINUX_KERNEL
+void DelayUS(ULONG MicroSeconds)
+{
+       udelay(MicroSeconds);
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+/* Function : XGIInitNew */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+
+    VB_DEVICE_INFO VBINF;
+    PVB_DEVICE_INFO pVBInfo = &VBINF;
+    UCHAR   i , temp = 0 , temp1 ;
+     //       VBIOSVersion[ 5 ] ;
+    PUCHAR  volatile pVideoMemory;
+
+    /* ULONG j, k ; */
+
+    PXGI_DSReg pSR ;
+
+    ULONG Temp ;
+
+    pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+
+    pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+
+    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+
+    pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr;
+
+
+//    Newdebugcode( 0x99 ) ;
+
+
+   /* if ( pVBInfo->ROMAddr == 0 ) */
+   /* return( FALSE ) ; */
+
+    if ( pVBInfo->FBAddr == 0 )
+{
+       printk("\n pVBInfo->FBAddr == 0 ");
+       return( FALSE ) ;
+}
+printk("1");
+    if ( pVBInfo->BaseAddr == 0 )
+{
+       printk("\npVBInfo->BaseAddr == 0 ");
+        return( FALSE ) ;
+}
+printk("2");
+
+    XGINew_SetReg3( ( pVBInfo->BaseAddr + 0x12 ) , 0x67 ) ;    /* 3c2 <- 67 ,ynlai */
+
+    pVBInfo->ISXPDOS = 0 ;
+printk("3");
+
+if ( !HwDeviceExtension->bIntegratedMMEnabled )
+{
+        return( FALSE ) ;      /* alan */
+}
+printk("4");
+
+//    XGI_MemoryCopy( VBIOSVersion , HwDeviceExtension->szVBIOSVer , 4 ) ;
+
+ //   VBIOSVersion[ 4 ] = 0x0 ;
+
+    /* 09/07/99 modify by domao */
+
+    pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+    pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+    pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+    pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+    pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+    pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+    pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+    pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+    pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+    pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+    pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+    pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+    pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+    pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+    pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+    pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+    pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+printk("5");
+
+    if ( HwDeviceExtension->jChipType < XG20 )                 /* kuku 2004/06/25 */
+    XGI_GetVBType( pVBInfo ) ;         /* Run XGI_GetVBType before InitTo330Pointer */
+
+    InitTo330Pointer( HwDeviceExtension->jChipType,  pVBInfo ) ;
+
+    /* ReadVBIOSData */
+    ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+
+    /* 1.Openkey */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
+printk("6");
+
+    /* GetXG21Sense (GPIO) */
+    if ( HwDeviceExtension->jChipType == XG21 )
+    {
+       XGINew_GetXG21Sense(HwDeviceExtension, pVBInfo) ;
+    }
+    if ( HwDeviceExtension->jChipType == XG27 )
+    {
+       XGINew_GetXG27Sense(HwDeviceExtension, pVBInfo) ;
+    }
+printk("7");
+
+    /* 2.Reset Extended register */
+
+    for( i = 0x06 ; i < 0x20 ; i++ )
+        XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
+
+    for( i = 0x21 ; i <= 0x27 ; i++ )
+        XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
+
+    /* for( i = 0x06 ; i <= 0x27 ; i++ ) */
+    /* XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ; */
+
+printk("8");
+
+    if(( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40))
+    {
+        for( i = 0x31 ; i <= 0x3B ; i++ )
+            XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
+    }
+    else
+    {
+        for( i = 0x31 ; i <= 0x3D ; i++ )
+            XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
+    }
+printk("9");
+
+    if ( HwDeviceExtension->jChipType == XG42 )                        /* [Hsuan] 2004/08/20 Auto over driver for XG42 */
+      XGINew_SetReg1( pVBInfo->P3c4 , 0x3B , 0xC0 ) ;
+
+    /* for( i = 0x30 ; i <= 0x3F ; i++ ) */
+    /* XGINew_SetReg1( pVBInfo->P3d4 , i , 0 ) ; */
+
+    for( i = 0x79 ; i <= 0x7C ; i++ )
+        XGINew_SetReg1( pVBInfo->P3d4 , i , 0 ) ;              /* shampoo 0208 */
+
+printk("10");
+
+    if ( HwDeviceExtension->jChipType >= XG20 )
+        XGINew_SetReg1( pVBInfo->P3d4 , 0x97 , *pVBInfo->pXGINew_CR97 ) ;
+
+    /* 3.SetMemoryClock
+
+    if ( HwDeviceExtension->jChipType >= XG40 )
+        XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo) ;
+
+    if ( HwDeviceExtension->jChipType < XG40 )
+        XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;  */
+
+printk("11");
+
+    /* 4.SetDefExt1Regs begin */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x07 , *pVBInfo->pSR07 ) ;
+    if ( HwDeviceExtension->jChipType == XG27 )
+    {
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x40 , *pVBInfo->pSR40 ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x41 , *pVBInfo->pSR41 ) ;
+    }
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x11 , 0x0F ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , *pVBInfo->pSR1F ) ;
+    /* XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0x20 ) ; */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0xA0 ) ;    /* alan, 2001/6/26 Frame buffer can read/write SR20 */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x36 , 0x70 ) ;    /* Hsuan, 2006/01/01 H/W request for slow corner chip */
+    if ( HwDeviceExtension->jChipType == XG27 )         /* Alan 12/07/2006 */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x36 , *pVBInfo->pSR36 ) ;
+
+    /* SR11 = 0x0F ; */
+    /* XGINew_SetReg1( pVBInfo->P3c4 , 0x11 , SR11 ) ; */
+
+printk("12");
+
+   if ( HwDeviceExtension->jChipType < XG20 )          /* kuku 2004/06/25 */
+    {
+//    /* Set AGP Rate */
+//    temp1 = XGINew_GetReg1( pVBInfo->P3c4 , 0x3B ) ;
+//    temp1 &= 0x02 ;
+//    if ( temp1 == 0x02 )
+//    {
+//        XGINew_SetReg4( 0xcf8 , 0x80000000 ) ;
+//       ChipsetID = XGINew_GetReg3( 0x0cfc ) ;
+//        XGINew_SetReg4( 0xcf8 , 0x8000002C ) ;
+//        VendorID = XGINew_GetReg3( 0x0cfc ) ;
+//        VendorID &= 0x0000FFFF ;
+//        XGINew_SetReg4( 0xcf8 , 0x8001002C ) ;
+//        GraphicVendorID = XGINew_GetReg3( 0x0cfc ) ;
+//        GraphicVendorID &= 0x0000FFFF;
+//
+//        if ( ChipsetID == 0x7301039 )
+///            XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x09 ) ;
+//
+//        ChipsetID &= 0x0000FFFF ;
+///
+//        if ( ( ChipsetID == 0x700E ) || ( ChipsetID == 0x1022 ) || ( ChipsetID == 0x1106 ) || ( ChipsetID == 0x10DE ) )
+//        {
+//            if ( ChipsetID == 0x1106 )
+//            {
+//                if ( ( VendorID == 0x1019 ) && ( GraphicVendorID == 0x1019 ) )
+//                    XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0D ) ;
+//                else
+//                    XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0B ) ;
+//            }
+//            else
+//                XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0B ) ;
+//        }
+//    }
+
+printk("13");
+
+    if ( HwDeviceExtension->jChipType >= XG40 )
+    {
+        /* Set AGP customize registers (in SetDefAGPRegs) Start */
+        for( i = 0x47 ; i <= 0x4C ; i++ )
+            XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ i - 0x47 ] ) ;
+
+        for( i = 0x70 ; i <= 0x71 ; i++ )
+            XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ 6 + i - 0x70 ] ) ;
+
+        for( i = 0x74 ; i <= 0x77 ; i++ )
+            XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ 8 + i - 0x74 ] ) ;
+        /* Set AGP customize registers (in SetDefAGPRegs) End */
+        /*[Hsuan]2004/12/14 AGP Input Delay Adjustment on 850 */
+//        XGINew_SetReg4( 0xcf8 , 0x80000000 ) ;
+//        ChipsetID = XGINew_GetReg3( 0x0cfc ) ;
+//        if ( ChipsetID == 0x25308086 )
+//            XGINew_SetReg1( pVBInfo->P3d4 , 0x77 , 0xF0 ) ;
+
+        HwDeviceExtension->pQueryVGAConfigSpace( HwDeviceExtension , 0x50 , 0 , &Temp ) ;      /* Get */
+        Temp >>= 20 ;
+        Temp &= 0xF ;
+
+        if ( Temp == 1 )
+            XGINew_SetReg1( pVBInfo->P3d4 , 0x48 , 0x20 ) ;    /* CR48 */
+    }
+printk("14");
+
+    if ( HwDeviceExtension->jChipType < XG40 )
+        XGINew_SetReg1( pVBInfo->P3d4 , 0x49 , pVBInfo->CR49[ 0 ] ) ;
+    }  /* != XG20 */
+
+    /* Set PCI */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x23 , *pVBInfo->pSR23 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x24 , *pVBInfo->pSR24 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x25 , pVBInfo->SR25[ 0 ] ) ;
+printk("15");
+
+    if ( HwDeviceExtension->jChipType < XG20 )         /* kuku 2004/06/25 */
+    {
+    /* Set VB */
+    XGI_UnLockCRT2( HwDeviceExtension, pVBInfo) ;
+    XGINew_SetRegANDOR( pVBInfo->Part0Port , 0x3F , 0xEF , 0x00 ) ;    /* alan, disable VideoCapture */
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , 0x00 ) ;
+    temp1 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x7B ) ;          /* chk if BCLK>=100MHz */
+    temp = ( UCHAR )( ( temp1 >> 4 ) & 0x0F ) ;
+
+
+        XGINew_SetReg1( pVBInfo->Part1Port , 0x02 , ( *pVBInfo->pCRT2Data_1_2 ) ) ;
+
+printk("16");
+
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x2E , 0x08 ) ;       /* use VB */
+    } /* != XG20 */
+
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x27 , 0x1F ) ;
+
+    if ( ( HwDeviceExtension->jChipType == XG42 ) && XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo) != 0 )       /* Not DDR */
+    {
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , ( *pVBInfo->pSR31 & 0x3F ) | 0x40 ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , ( *pVBInfo->pSR32 & 0xFC ) | 0x01 ) ;
+    }
+    else
+    {
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , *pVBInfo->pSR31 ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , *pVBInfo->pSR32 ) ;
+    }
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x33 , *pVBInfo->pSR33 ) ;
+printk("17");
+
+/*
+    if ( HwDeviceExtension->jChipType >= XG40 )
+      SetPowerConsume ( HwDeviceExtension , pVBInfo->P3c4);    */
+
+    if ( HwDeviceExtension->jChipType < XG20 )         /* kuku 2004/06/25 */
+    {
+    if ( XGI_BridgeIsOn( pVBInfo ) == 1 )
+    {
+        if ( pVBInfo->IF_DEF_LVDS == 0 )
+        {
+            XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , 0x1C ) ;
+            XGINew_SetReg1( pVBInfo->Part4Port , 0x0D , *pVBInfo->pCRT2Data_4_D ) ;
+            XGINew_SetReg1( pVBInfo->Part4Port , 0x0E , *pVBInfo->pCRT2Data_4_E ) ;
+            XGINew_SetReg1( pVBInfo->Part4Port , 0x10 , *pVBInfo->pCRT2Data_4_10 ) ;
+            XGINew_SetReg1( pVBInfo->Part4Port , 0x0F , 0x3F ) ;
+        }
+
+        XGI_LockCRT2( HwDeviceExtension, pVBInfo ) ;
+    }
+    }  /* != XG20 */
+printk("18");
+
+    if ( HwDeviceExtension->jChipType < XG40 )
+        XGINew_SetReg1( pVBInfo->P3d4 , 0x83 , 0x00 ) ;
+printk("181");
+
+    if ( HwDeviceExtension->bSkipSense == FALSE )
+    {
+printk("182");
+
+        XGI_SenseCRT1(pVBInfo) ;
+
+printk("183");
+        /* XGINew_DetectMonitor( HwDeviceExtension ) ; */
+pVBInfo->IF_DEF_CH7007 = 0;
+        if ( ( HwDeviceExtension->jChipType == XG21 ) && (pVBInfo->IF_DEF_CH7007) )
+        {
+printk("184");
+           XGI_GetSenseStatus( HwDeviceExtension , pVBInfo ) ;         /* sense CRT2 */
+printk("185");
+
+        }
+        if ( HwDeviceExtension->jChipType == XG21 )
+        {
+printk("186");
+
+          XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~Monitor1Sense , Monitor1Sense ) ;        /* Z9 default has CRT */
+                 temp = GetXG21FPBits( pVBInfo ) ;
+          XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~0x01, temp ) ;
+printk("187");
+
+          }
+        if ( HwDeviceExtension->jChipType == XG27 )
+        {
+          XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~Monitor1Sense , Monitor1Sense ) ;        /* Z9 default has CRT */
+                 temp = GetXG27FPBits( pVBInfo ) ;
+          XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~0x03, temp ) ;
+        }
+    }
+printk("19");
+
+    if ( HwDeviceExtension->jChipType >= XG40 )
+    {
+        if ( HwDeviceExtension->jChipType >= XG40 )
+        {
+          XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+         }
+
+        XGINew_SetDRAMDefaultRegister340( HwDeviceExtension ,  pVBInfo->P3d4,  pVBInfo ) ;
+
+        if ( HwDeviceExtension->bSkipDramSizing == TRUE )
+        {
+            pSR = HwDeviceExtension->pSR ;
+            if ( pSR!=NULL )
+            {
+                while( pSR->jIdx != 0xFF )
+                {
+                    XGINew_SetReg1( pVBInfo->P3c4 , pSR->jIdx , pSR->jVal ) ;
+                    pSR++ ;
+                }
+            }
+            /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */
+        }      /* SkipDramSizing */
+        else
+        {
+#if 0
+           if ( HwDeviceExtension->jChipType == XG20 )
+            {
+               XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , pVBInfo->SR15[0][XGINew_RAMType] ) ;
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , pVBInfo->SR15[1][XGINew_RAMType] ) ;
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0x20 ) ;
+            }
+            else
+#endif
+{
+printk("20");
+
+               XGINew_SetDRAMSize_340( HwDeviceExtension , pVBInfo) ;
+}
+printk("21");
+
+        }
+    }          /* XG40 */
+
+printk("22");
+
+
+    /* SetDefExt2Regs begin */
+/*
+    AGP = 1 ;
+    temp =( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) ;
+    temp &= 0x30 ;
+    if ( temp == 0x30 )
+        AGP = 0 ;
+
+    if ( AGP == 0 )
+        *pVBInfo->pSR21 &= 0xEF ;
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , *pVBInfo->pSR21 ) ;
+    if ( AGP == 1 )
+        *pVBInfo->pSR22 &= 0x20 ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , *pVBInfo->pSR22 ) ;
+*/
+
+//    base = 0x80000000 ;
+//    OutPortLong( 0xcf8 , base ) ;
+//    Temp = ( InPortLong( 0xcfc ) & 0xFFFF ) ;
+//    if ( Temp == 0x1039 )
+//    {
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , ( UCHAR )( ( *pVBInfo->pSR22 ) & 0xFE ) ) ;
+//    }
+//    else
+//    {
+//        XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , *pVBInfo->pSR22 ) ;
+//    }
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , *pVBInfo->pSR21 ) ;
+
+printk("23");
+
+
+    XGINew_ChkSenseStatus ( HwDeviceExtension , pVBInfo ) ;
+    XGINew_SetModeScratch ( HwDeviceExtension , pVBInfo ) ;
+
+printk("24");
+
+
+XGINew_SetReg1( pVBInfo->P3d4 , 0x8c , 0x87);
+XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x31);
+printk("25");
+
+    return( TRUE ) ;
+} /* end of init */
+
+
+
+
+
+/* ============== alan ====================== */
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_GetXG20DRAMType */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR data, temp ;
+
+    if ( HwDeviceExtension->jChipType < XG20 )
+    {
+        if ( *pVBInfo->pSoftSetting & SoftDRAMType )
+        {
+            data = *pVBInfo->pSoftSetting & 0x07 ;
+            return( data ) ;
+        }
+        else
+        {
+            data = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) & 0x02 ;
+
+            if ( data == 0 )
+                data = ( XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) & 0x02 ) >> 1 ;
+
+            return( data ) ;
+        }
+    }
+    else if ( HwDeviceExtension->jChipType == XG27 )
+    {
+        if ( *pVBInfo->pSoftSetting & SoftDRAMType )
+        {
+            data = *pVBInfo->pSoftSetting & 0x07 ;
+            return( data ) ;
+        }
+        temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3B ) ;
+
+       if (( temp & 0x88 )==0x80)              /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */
+                 data = 0 ;                                    /*DDR*/
+        else
+                 data = 1 ;                                    /*DDRII*/
+               return( data ) ;
+    }
+    else if ( HwDeviceExtension->jChipType == XG21 )
+    {
+        XGINew_SetRegAND( pVBInfo->P3d4 , 0xB4 , ~0x02 ) ;                     /* Independent GPIO control */
+       DelayUS(800);
+        XGINew_SetRegOR( pVBInfo->P3d4 , 0x4A , 0x80 ) ;               /* Enable GPIOH read */
+        temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;                /* GPIOF 0:DVI 1:DVO */
+// HOTPLUG_SUPPORT
+// for current XG20 & XG21, GPIOH is floating, driver will fix DDR temporarily
+       if ( temp & 0x01 )                                              /* DVI read GPIOH */
+                 data = 1 ;                                                    /*DDRII*/
+        else
+                 data = 0 ;                                                    /*DDR*/
+//~HOTPLUG_SUPPORT
+               XGINew_SetRegOR( pVBInfo->P3d4 , 0xB4 , 0x02 ) ;
+               return( data ) ;
+    }
+    else
+    {
+       data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) & 0x01 ;
+
+       if ( data == 1 )
+            data ++ ;
+
+       return( data );
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_Get310DRAMType */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGINew_Get310DRAMType(PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR data ;
+
+  /* index = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ; */
+  /* index &= 07 ; */
+
+    if ( *pVBInfo->pSoftSetting & SoftDRAMType )
+        data = *pVBInfo->pSoftSetting & 0x03 ;
+    else
+        data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3a ) & 0x03 ;
+
+    return( data ) ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_Delay15us */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+/*
+void XGINew_Delay15us(ULONG ulMicrsoSec)
+{
+}
+*/
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SDR_MRS */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SDR_MRS(  PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT data ;
+
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ;
+    data &= 0x3F ;          /* SR16 D7=0,D6=0 */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;   /* enable mode register set(MRS) low */
+    /* XGINew_Delay15us( 0x100 ) ; */
+    data |= 0x80 ;          /* SR16 D7=1,D6=0 */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;   /* enable mode register set(MRS) high */
+    /* XGINew_Delay15us( 0x100 ) ; */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR1x_MRS_340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR1x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+    XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ;
+    XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+    if ( *pVBInfo->pXGINew_DRAMTypeDefinition != 0x0C )        /* Samsung F Die */
+    {
+        DelayUS( 3000 ) ;      /* Delay 67 x 3 Delay15us */
+        XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;
+        XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
+        XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+        XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+    }
+
+    DelayUS( 60 ) ;
+    XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ;     /* SR18 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 0 ] ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 1 ] ) ;
+    DelayUS( 1000 ) ;
+    XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ;
+    DelayUS( 500 ) ;
+    XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ;     /* SR18 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 2 ] ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 3 ] ) ;
+    XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR2x_MRS_340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR2x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;
+    XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+    DelayUS( 60 ) ;
+    XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ;     /* SR18 */
+    /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+    DelayUS( 1000 ) ;
+    XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ;
+    DelayUS( 500 ) ;
+    /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
+    XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ;     /* SR18 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+    XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDRII_Bootup_XG27 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDRII_Bootup_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+    ULONG P3d4 = P3c4 + 0x10 ;
+    XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+    XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+
+   /* Set Double Frequency */
+    /* XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ; */               /* CR97 */
+    XGINew_SetReg1( P3d4 , 0x97 , *pVBInfo->pXGINew_CR97 ) ;    /* CR97 */
+
+    DelayUS( 200 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;   /* Set SR18 */ //EMRS2
+    XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ;   /* Set SR19 */
+    XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ;   /* Set SR16 */
+    DelayUS( 15 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ;   /* Set SR16 */
+    DelayUS( 15 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;   /* Set SR18 */ //EMRS3
+    XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ;   /* Set SR19 */
+    XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ;   /* Set SR16 */
+    DelayUS( 15 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ;   /* Set SR16 */
+    DelayUS( 15) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;   /* Set SR18 */ //EMRS1
+    XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;   /* Set SR19 */
+    XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ;   /* Set SR16 */
+    DelayUS( 30 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ;   /* Set SR16 */
+    DelayUS( 15 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ;   /* Set SR18 */ //MRS, DLL Enable
+    XGINew_SetReg1( P3c4 , 0x19 , 0x0A ) ;   /* Set SR19 */
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;   /* Set SR16 */
+    DelayUS( 30 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;   /* Set SR16 */
+    XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;   /* Set SR16 */
+    /* DelayUS( 15 ) ; */
+
+    XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ;   /* Set SR1B */
+    DelayUS( 60 ) ;
+    XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;   /* Set SR1B */
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ;   /* Set SR18 */ //MRS, DLL Reset
+    XGINew_SetReg1( P3c4 , 0x19 , 0x08 ) ;   /* Set SR19 */
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;   /* Set SR16 */
+
+    DelayUS( 30 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ;   /* Set SR16 */
+    DelayUS( 15 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x80 ) ;   /* Set SR18 */ //MRS, ODT
+    XGINew_SetReg1( P3c4 , 0x19 , 0x46 ) ;   /* Set SR19 */
+    XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ;   /* Set SR16 */
+    DelayUS( 30 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ;   /* Set SR16 */
+    DelayUS( 15 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;   /* Set SR18 */ //EMRS
+    XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;   /* Set SR19 */
+    XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ;   /* Set SR16 */
+    DelayUS( 30 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ;   /* Set SR16 */
+    DelayUS( 15 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ;   /* Set SR1B refresh control 000:close; 010:open */
+    DelayUS( 200 ) ;
+
+
+}
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR2_MRS_XG20 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR2_MRS_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+    ULONG P3d4 = P3c4 + 0x10 ;
+
+    XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+    XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+
+    XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ;                     /* CR97 */
+
+    DelayUS( 200 ) ;
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;                     /* EMRS2 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;                     /* EMRS3 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;                     /* EMRS1 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+
+   // XGINew_SetReg1( P3c4 , 0x18 , 0x52 ) ;                   /* MRS1 */
+    XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ;                     /* MRS1 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x02 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+
+    DelayUS( 15 ) ;
+    XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ;                     /* SR1B */
+    DelayUS( 30 ) ;
+    XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;                     /* SR1B */
+    DelayUS( 100 ) ;
+
+    //XGINew_SetReg1( P3c4 , 0x18 , 0x52 ) ;                   /* MRS2 */
+    XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ;                     /* MRS1 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+
+    DelayUS( 200 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR2_MRS_XG20 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR2_MRS_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+    ULONG P3d4 = P3c4 + 0x10 ;
+
+     XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+     XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+
+    XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ;                     /* CR97 */
+    DelayUS( 200 ) ;
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;                     /* EMRS2 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x16 , 0x10 ) ;
+    DelayUS( 15 ) ;                          ////06/11/23 XG27 A0 for CKE enable
+    XGINew_SetReg1( P3c4 , 0x16 , 0x90 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;                     /* EMRS3 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+    DelayUS( 15 ) ;                          ////06/11/22 XG27 A0
+    XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;                     /* EMRS1 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+    DelayUS( 15 ) ;                          ////06/11/22 XG27 A0
+    XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ;                     /* MRS1 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x06 ) ;   ////[Billy]06/11/22 DLL Reset for XG27 Hynix DRAM
+
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+    DelayUS( 15 ) ;                          ////06/11/23 XG27 A0
+    XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+    DelayUS( 30 ) ;                          ////06/11/23 XG27 A0 Start Auto-PreCharge
+    XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ;                     /* SR1B */
+    DelayUS( 60 ) ;
+    XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;                     /* SR1B */
+
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ;                     /* MRS1 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x04 ) ;   //// DLL without Reset for XG27 Hynix DRAM
+
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+    DelayUS( 30 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x80 );     ////XG27 OCD ON
+    XGINew_SetReg1( P3c4 , 0x19 , 0x46 );
+
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+    DelayUS( 30 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 );
+    XGINew_SetReg1( P3c4 , 0x19 , 0x40 );
+
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+    DelayUS( 30 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+    DelayUS( 15 ) ;                         ////Start Auto-PreCharge
+    XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ;                     /* SR1B */
+    DelayUS( 200 ) ;
+    XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ;                     /* SR1B */
+
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR1x_DefaultRegister */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR1x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG Port , PVB_DEVICE_INFO pVBInfo)
+{
+    ULONG P3d4 = Port ,
+           P3c4 = Port - 0x10 ;
+
+    if ( HwDeviceExtension->jChipType >= XG20 )
+    {
+        XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+        XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ;        /* CR82 */
+        XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ;        /* CR85 */
+        XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ;        /* CR86 */
+
+        XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
+        XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
+
+        XGINew_DDR1x_MRS_XG20( P3c4 , pVBInfo) ;
+    }
+    else
+    {
+        XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+
+        switch( HwDeviceExtension->jChipType )
+        {
+            case XG41:
+            case XG42:
+                XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ;        /* CR82 */
+                XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ;        /* CR85 */
+                XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ;        /* CR86 */
+                break ;
+            default:
+                XGINew_SetReg1( P3d4 , 0x82 , 0x88 ) ;
+                XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ;
+                XGINew_GetReg1( P3d4 , 0x86 ) ;                                /* Insert read command for delay */
+                XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ;
+                XGINew_GetReg1( P3d4 , 0x86 ) ;
+                XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ;
+                XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
+                XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ;
+                XGINew_GetReg1( P3d4 , 0x85 ) ;                                /* Insert read command for delay */
+                XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ;
+                XGINew_GetReg1( P3d4 , 0x85 ) ;                                /* Insert read command for delay */
+                XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ;        /* CR85 */
+                XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ;        /* CR82 */
+                break ;
+        }
+
+        XGINew_SetReg1( P3d4 , 0x97 , 0x00 ) ;
+        XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
+        XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
+        XGINew_DDR1x_MRS_340( P3c4 , pVBInfo ) ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR2x_DefaultRegister */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR2x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG Port ,PVB_DEVICE_INFO pVBInfo)
+{
+    ULONG P3d4 = Port ,
+           P3c4 = Port - 0x10 ;
+
+    XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+
+    /* 20040906 Hsuan modify CR82, CR85, CR86 for XG42 */
+    switch( HwDeviceExtension->jChipType )
+    {
+       case XG41:
+       case XG42:
+            XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ;    /* CR82 */
+            XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ;    /* CR85 */
+            XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ;    /* CR86 */
+            break ;
+       default:
+         /* keep following setting sequence, each setting in the same reg insert idle */
+         XGINew_SetReg1( P3d4 , 0x82 , 0x88 ) ;
+        XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ;
+        XGINew_GetReg1( P3d4 , 0x86 ) ;                                /* Insert read command for delay */
+        XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ;
+        XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
+        XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ;
+        XGINew_GetReg1( P3d4 , 0x85 ) ;                                /* Insert read command for delay */
+        XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ;
+        XGINew_GetReg1( P3d4 , 0x85 ) ;                                /* Insert read command for delay */
+        XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ;        /* CR85 */
+        XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ;        /* CR82 */
+    }
+    XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ;
+    if ( HwDeviceExtension->jChipType == XG42 )
+    {
+      XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
+    }
+    else
+    {
+      XGINew_SetReg1( P3d4 , 0x98 , 0x03 ) ;
+    }
+    XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
+
+    XGINew_DDR2x_MRS_340( P3c4 , pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR2_DefaultRegister */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR2_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension, ULONG Port , PVB_DEVICE_INFO pVBInfo)
+{
+    ULONG P3d4 = Port ,
+           P3c4 = Port - 0x10 ;
+
+    /* keep following setting sequence, each setting in the same reg insert idle */
+    XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
+    XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ;
+    XGINew_GetReg1( P3d4 , 0x86 ) ;                            /* Insert read command for delay */
+    XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ;
+    XGINew_GetReg1( P3d4 , 0x86 ) ;                            /* Insert read command for delay */
+    XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ;    /* CR86 */
+    XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
+    XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ;
+    XGINew_GetReg1( P3d4 , 0x85 ) ;                            /* Insert read command for delay */
+    XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ;
+    XGINew_GetReg1( P3d4 , 0x85 ) ;                            /* Insert read command for delay */
+    XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ;    /* CR85 */
+    if ( HwDeviceExtension->jChipType == XG27 )
+      XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ;  /* CR82 */
+    else
+    XGINew_SetReg1( P3d4 , 0x82 , 0xA8 ) ;     /* CR82 */
+
+    XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
+    XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
+    if ( HwDeviceExtension->jChipType == XG27 )
+       XGINew_DDRII_Bootup_XG27( HwDeviceExtension ,  P3c4 , pVBInfo) ;
+    else
+    XGINew_DDR2_MRS_XG20( HwDeviceExtension , P3c4, pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMDefaultRegister340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMDefaultRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG Port , PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR temp , temp1 , temp2 , temp3 ,
+          i , j , k ;
+
+    ULONG P3d4 = Port ,
+           P3c4 = Port - 0x10 ;
+
+    XGINew_SetReg1( P3d4 , 0x6D , pVBInfo->CR40[ 8 ][ XGINew_RAMType ] ) ;
+    XGINew_SetReg1( P3d4 , 0x68 , pVBInfo->CR40[ 5 ][ XGINew_RAMType ] ) ;
+    XGINew_SetReg1( P3d4 , 0x69 , pVBInfo->CR40[ 6 ][ XGINew_RAMType ] ) ;
+    XGINew_SetReg1( P3d4 , 0x6A , pVBInfo->CR40[ 7 ][ XGINew_RAMType ] ) ;
+
+    temp2 = 0 ;
+    for( i = 0 ; i < 4 ; i++ )
+    {
+        temp = pVBInfo->CR6B[ XGINew_RAMType ][ i ] ;                  /* CR6B DQS fine tune delay */
+        for( j = 0 ; j < 4 ; j++ )
+        {
+            temp1 = ( ( temp >> ( 2 * j ) ) & 0x03 ) << 2 ;
+            temp2 |= temp1 ;
+            XGINew_SetReg1( P3d4 , 0x6B , temp2 ) ;
+            XGINew_GetReg1( P3d4 , 0x6B ) ;                            /* Insert read command for delay */
+            temp2 &= 0xF0 ;
+            temp2 += 0x10 ;
+        }
+    }
+
+    temp2 = 0 ;
+    for( i = 0 ; i < 4 ; i++ )
+    {
+        temp = pVBInfo->CR6E[ XGINew_RAMType ][ i ] ;                  /* CR6E DQM fine tune delay */
+        for( j = 0 ; j < 4 ; j++ )
+        {
+            temp1 = ( ( temp >> ( 2 * j ) ) & 0x03 ) << 2 ;
+            temp2 |= temp1 ;
+            XGINew_SetReg1( P3d4 , 0x6E , temp2 ) ;
+            XGINew_GetReg1( P3d4 , 0x6E ) ;                            /* Insert read command for delay */
+            temp2 &= 0xF0 ;
+            temp2 += 0x10 ;
+        }
+    }
+
+    temp3 = 0 ;
+    for( k = 0 ; k < 4 ; k++ )
+    {
+        XGINew_SetRegANDOR( P3d4 , 0x6E , 0xFC , temp3 ) ;             /* CR6E_D[1:0] select channel */
+        temp2 = 0 ;
+        for( i = 0 ; i < 8 ; i++ )
+        {
+            temp = pVBInfo->CR6F[ XGINew_RAMType ][ 8 * k + i ] ;      /* CR6F DQ fine tune delay */
+            for( j = 0 ; j < 4 ; j++ )
+            {
+                temp1 = ( temp >> ( 2 * j ) ) & 0x03 ;
+                temp2 |= temp1 ;
+                XGINew_SetReg1( P3d4 , 0x6F , temp2 ) ;
+                XGINew_GetReg1( P3d4 , 0x6F ) ;                                /* Insert read command for delay */
+                temp2 &= 0xF8 ;
+                temp2 += 0x08 ;
+            }
+        }
+        temp3 += 0x01 ;
+    }
+
+    XGINew_SetReg1( P3d4 , 0x80 , pVBInfo->CR40[ 9 ][ XGINew_RAMType ] ) ;     /* CR80 */
+    XGINew_SetReg1( P3d4 , 0x81 , pVBInfo->CR40[ 10 ][ XGINew_RAMType ] ) ;    /* CR81 */
+
+    temp2 = 0x80 ;
+    temp = pVBInfo->CR89[ XGINew_RAMType ][ 0 ] ;                      /* CR89 terminator type select */
+    for( j = 0 ; j < 4 ; j++ )
+    {
+        temp1 = ( temp >> ( 2 * j ) ) & 0x03 ;
+        temp2 |= temp1 ;
+        XGINew_SetReg1( P3d4 , 0x89 , temp2 ) ;
+        XGINew_GetReg1( P3d4 , 0x89 ) ;                                /* Insert read command for delay */
+        temp2 &= 0xF0 ;
+        temp2 += 0x10 ;
+    }
+
+    temp = pVBInfo->CR89[ XGINew_RAMType ][ 1 ] ;
+    temp1 = temp & 0x03 ;
+    temp2 |= temp1 ;
+    XGINew_SetReg1( P3d4 , 0x89 , temp2 ) ;
+
+    temp = pVBInfo->CR40[ 3 ][ XGINew_RAMType ] ;
+    temp1 = temp & 0x0F ;
+    temp2 = ( temp >> 4 ) & 0x07 ;
+    temp3 = temp & 0x80 ;
+    XGINew_SetReg1( P3d4 , 0x45 , temp1 ) ;    /* CR45 */
+    XGINew_SetReg1( P3d4 , 0x99 , temp2 ) ;    /* CR99 */
+    XGINew_SetRegOR( P3d4 , 0x40 , temp3 ) ;   /* CR40_D[7] */
+    XGINew_SetReg1( P3d4 , 0x41 , pVBInfo->CR40[ 0 ][ XGINew_RAMType ] ) ;     /* CR41 */
+
+    if ( HwDeviceExtension->jChipType == XG27 )
+      XGINew_SetReg1( P3d4 , 0x8F , *pVBInfo->pCR8F ) ;        /* CR8F */
+
+    for( j = 0 ; j <= 6 ; j++ )
+        XGINew_SetReg1( P3d4 , ( 0x90 + j ) , pVBInfo->CR40[ 14 + j ][ XGINew_RAMType ] ) ;    /* CR90 - CR96 */
+
+    for( j = 0 ; j <= 2 ; j++ )
+        XGINew_SetReg1( P3d4 , ( 0xC3 + j ) , pVBInfo->CR40[ 21 + j ][ XGINew_RAMType ] ) ;    /* CRC3 - CRC5 */
+
+    for( j = 0 ; j < 2 ; j++ )
+        XGINew_SetReg1( P3d4 , ( 0x8A + j ) , pVBInfo->CR40[ 1 + j ][ XGINew_RAMType ] ) ;     /* CR8A - CR8B */
+
+    if ( ( HwDeviceExtension->jChipType == XG41 ) || ( HwDeviceExtension->jChipType == XG42 ) )
+        XGINew_SetReg1( P3d4 , 0x8C , 0x87 ) ;
+
+    XGINew_SetReg1( P3d4 , 0x59 , pVBInfo->CR40[ 4 ][ XGINew_RAMType ] ) ;     /* CR59 */
+
+    XGINew_SetReg1( P3d4 , 0x83 , 0x09 ) ;     /* CR83 */
+    XGINew_SetReg1( P3d4 , 0x87 , 0x00 ) ;     /* CR87 */
+    XGINew_SetReg1( P3d4 , 0xCF , *pVBInfo->pCRCF ) ;  /* CRCF */
+    if ( XGINew_RAMType )
+    {
+      //XGINew_SetReg1( P3c4 , 0x17 , 0xC0 ) ;         /* SR17 DDRII */
+      XGINew_SetReg1( P3c4 , 0x17 , 0x80 ) ;           /* SR17 DDRII */
+      if ( HwDeviceExtension->jChipType == XG27 )
+        XGINew_SetReg1( P3c4 , 0x17 , 0x02 ) ;         /* SR17 DDRII */
+
+    }
+    else
+      XGINew_SetReg1( P3c4 , 0x17 , 0x00 ) ;           /* SR17 DDR */
+    XGINew_SetReg1( P3c4 , 0x1A , 0x87 ) ;             /* SR1A */
+
+    temp = XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) ;
+    if( temp == 0 )
+      XGINew_DDR1x_DefaultRegister( HwDeviceExtension, P3d4, pVBInfo ) ;
+    else
+    {
+      XGINew_SetReg1( P3d4 , 0xB0 , 0x80 ) ;           /* DDRII Dual frequency mode */
+      XGINew_DDR2_DefaultRegister( HwDeviceExtension, P3d4, pVBInfo ) ;
+    }
+    XGINew_SetReg1( P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ;     /* SR1B */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR_MRS */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR_MRS(PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT data ;
+
+    PUCHAR volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
+
+    /* SR16 <- 1F,DF,2F,AF */
+    /* yriver modified SR16 <- 0F,DF,0F,AF */
+    /* enable DLL of DDR SD/SGRAM , SR16 D4=1 */
+    data = pVideoMemory[ 0xFB ] ;
+    /* data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ; */
+
+    data &= 0x0F ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+    data |= 0xC0 ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+    data &= 0x0F ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+    data |= 0x80 ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+    data &= 0x0F ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+    data |= 0xD0 ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+    data &= 0x0F ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+    data |= 0xA0 ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+/*
+   else {
+     data &= 0x0F;
+     data |= 0x10;
+     XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
+
+     if (!(pVBInfo->SR15[1][XGINew_RAMType] & 0x10))
+     {
+       data &= 0x0F;
+     }
+
+     data |= 0xC0;
+     XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
+
+
+     data &= 0x0F;
+     data |= 0x20;
+     XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
+     if (!(pVBInfo->SR15[1][XGINew_RAMType] & 0x10))
+     {
+       data &= 0x0F;
+     }
+
+     data |= 0x80;
+     XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
+   }
+*/
+}
+
+
+/* check if read cache pointer is correct */
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_VerifyMclk */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_VerifyMclk( PXGI_HW_DEVICE_INFO  HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+    PUCHAR pVideoMemory = pVBInfo->FBAddr ;
+    UCHAR i , j ;
+    USHORT Temp , SR21 ;
+
+    pVideoMemory[ 0 ] = 0xaa ;                 /* alan */
+    pVideoMemory[ 16 ] = 0x55 ;        /* note: PCI read cache is off */
+
+    if ( ( pVideoMemory[ 0 ] != 0xaa ) || ( pVideoMemory[ 16 ] != 0x55 ) )
+    {
+        for( i = 0 , j = 16 ; i < 2 ; i++ , j += 16 )
+        {
+            SR21 = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
+            Temp = SR21 & 0xFB ;       /* disable PCI post write buffer empty gating */
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , Temp ) ;
+
+            Temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3C ) ;
+            Temp |= 0x01 ;             /* MCLK reset */
+
+
+            Temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3C ) ;
+            Temp &= 0xFE ;             /* MCLK normal operation */
+
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , SR21 ) ;
+
+            pVideoMemory[ 16 + j ] = j ;
+            if ( pVideoMemory[ 16 + j ] == j )
+            {
+                pVideoMemory[ j ] = j ;
+                break ;
+            }
+        }
+    }
+}
+
+
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMSize_340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMSize_340( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT  data ;
+
+    pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+    pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+
+    XGISetModeNew( HwDeviceExtension , 0x2e ) ;
+
+
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data & 0xDF ) ) ;       /* disable read cache */
+    XGI_DisplayOff( HwDeviceExtension, pVBInfo );
+
+    /*data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1 ) ;*/
+    /*data |= 0x20 ;*/
+    /*XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ;*/                        /* Turn OFF Display */
+    XGINew_DDRSizing340( HwDeviceExtension, pVBInfo ) ;
+    data=XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data | 0x20 ) ) ;       /* enable read cache */
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMSize_310( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT data ;
+    pVBInfo->ROMAddr  = HwDeviceExtension->pjVirtualRomBase ,
+    pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+#ifdef XGI301
+    /* XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x40 ) ; */
+#endif
+
+#ifdef XGI302  /* alan,should change value */
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x4D ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x31 , 0xc0 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x34 , 0x3F ) ;
+#endif
+
+    XGISetModeNew( HwDeviceExtension , 0x2e ) ;
+
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data & 0xDF ) ) ;       /* disable read cache */
+
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1 ) ;
+    data |= 0x20 ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ;            /* Turn OFF Display */
+
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ;
+
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , ( USHORT )( data | 0x0F ) ) ;               /* assume lowest speed DRAM */
+
+    XGINew_SetDRAMModeRegister( pVBInfo ) ;
+    XGINew_DisableRefresh( HwDeviceExtension, pVBInfo ) ;
+    XGINew_CheckBusWidth_310( pVBInfo) ;
+    XGINew_VerifyMclk( HwDeviceExtension, pVBInfo ) ;  /* alan 2000/7/3 */
+
+
+
+    if ( XGINew_Get310DRAMType( pVBInfo ) < 2 )
+    {
+        XGINew_SDRSizing( pVBInfo ) ;
+    }
+    else
+    {
+        XGINew_DDRSizing( pVBInfo) ;
+    }
+
+
+
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , pVBInfo->SR15[ 1 ][ XGINew_RAMType ] ) ;    /* restore SR16 */
+
+    XGINew_EnableRefresh(  HwDeviceExtension, pVBInfo ) ;
+    data=XGINew_GetReg1( pVBInfo->P3c4 ,0x21 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data | 0x20 ) ) ;       /* enable read cache */
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMModeRegister340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+
+void XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+    UCHAR data ;
+    VB_DEVICE_INFO VBINF;
+    PVB_DEVICE_INFO pVBInfo = &VBINF;
+    pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+    pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+    pVBInfo->ISXPDOS = 0 ;
+
+    pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+    pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+    pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+    pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+    pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+    pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+    pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+    pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+    pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+    pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+    pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+    pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+    pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+    pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+    pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+    pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+    pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+    if ( HwDeviceExtension->jChipType < XG20 )                  /* kuku 2004/06/25 */
+    XGI_GetVBType( pVBInfo ) ;         /* Run XGI_GetVBType before InitTo330Pointer */
+
+    InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
+
+    ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+
+    if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
+    {
+        data = ( XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) & 0x02 ) >> 1 ;
+        if ( data == 0x01 )
+            XGINew_DDR2x_MRS_340( pVBInfo->P3c4, pVBInfo ) ;
+        else
+            XGINew_DDR1x_MRS_340( pVBInfo->P3c4, pVBInfo ) ;
+    }
+    else
+        XGINew_DDR2_MRS_XG20( HwDeviceExtension, pVBInfo->P3c4, pVBInfo);
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMModeRegister */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMModeRegister( PVB_DEVICE_INFO pVBInfo)
+{
+    if ( XGINew_Get310DRAMType( pVBInfo ) < 2 )
+    {
+      XGINew_SDR_MRS(pVBInfo ) ;
+    }
+    else
+    {
+      /* SR16 <- 0F,CF,0F,8F */
+      XGINew_DDR_MRS( pVBInfo ) ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DisableRefresh */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT  data ;
+
+
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1B ) ;
+    data &= 0xF8 ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , data ) ;
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_EnableRefresh */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ;    /* SR1B */
+
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DisableChannelInterleaving */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DisableChannelInterleaving( int index , USHORT XGINew_DDRDRAM_TYPE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT data ;
+
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x15 ) ;
+    data &= 0x1F ;
+
+    switch( XGINew_DDRDRAM_TYPE[ index ][ 3 ] )
+    {
+        case 64:
+            data |= 0 ;
+            break ;
+        case 32:
+            data |= 0x20 ;
+            break ;
+        case 16:
+            data |= 0x40 ;
+            break ;
+        case 4:
+            data |= 0x60 ;
+            break ;
+        default:
+            break ;
+    }
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMSizingType */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMSizingType( int index , USHORT DRAMTYPE_TABLE[][ 5 ] ,PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT data ;
+
+    data = DRAMTYPE_TABLE[ index ][ 4 ] ;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x13 , 0x80 , data ) ;
+    DelayUS( 15 ) ;
+   /* should delay 50 ns */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckBusWidth_310 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_CheckBusWidth_310(  PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT data ;
+    PULONG volatile pVideoMemory ;
+
+    pVideoMemory = (PULONG) pVBInfo->FBAddr;
+
+    if ( XGINew_Get310DRAMType( pVBInfo ) < 2 )
+    {
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x00 ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x12 ) ;
+        /* should delay */
+        XGINew_SDR_MRS( pVBInfo ) ;
+
+        XGINew_ChannelAB = 0 ;
+        XGINew_DataBusWidth = 128 ;
+        pVideoMemory[ 0 ] = 0x01234567L ;
+        pVideoMemory[ 1 ] = 0x456789ABL ;
+        pVideoMemory[ 2 ] = 0x89ABCDEFL ;
+        pVideoMemory[ 3 ] = 0xCDEF0123L ;
+        pVideoMemory[ 4 ] = 0x55555555L ;
+        pVideoMemory[ 5 ] = 0x55555555L ;
+        pVideoMemory[ 6 ] = 0xFFFFFFFFL ;
+        pVideoMemory[ 7 ] = 0xFFFFFFFFL ;
+
+        if ( ( pVideoMemory[ 3 ] != 0xCDEF0123L ) || ( pVideoMemory[ 2 ] != 0x89ABCDEFL ) )
+        {
+            /* ChannelA64Bit */
+            XGINew_DataBusWidth = 64 ;
+            XGINew_ChannelAB = 0 ;
+            data=XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( USHORT )( data & 0xFD ) ) ;
+        }
+
+        if ( ( pVideoMemory[ 1 ] != 0x456789ABL ) || ( pVideoMemory[ 0 ] != 0x01234567L ) )
+        {
+            /* ChannelB64Bit */
+            XGINew_DataBusWidth = 64 ;
+            XGINew_ChannelAB = 1 ;
+            data=XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( USHORT )( ( data & 0xFD ) | 0x01 ) ) ;
+        }
+
+        return ;
+    }
+    else
+    {
+        /* DDR Dual channel */
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x00 ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x02 ) ;        /* Channel A, 64bit */
+        /* should delay */
+        XGINew_DDR_MRS( pVBInfo ) ;
+
+        XGINew_ChannelAB = 0 ;
+        XGINew_DataBusWidth = 64 ;
+        pVideoMemory[ 0 ] = 0x01234567L ;
+        pVideoMemory[ 1 ] = 0x456789ABL ;
+        pVideoMemory[ 2 ] = 0x89ABCDEFL ;
+        pVideoMemory[ 3 ] = 0xCDEF0123L ;
+        pVideoMemory[ 4 ] = 0x55555555L ;
+        pVideoMemory[ 5 ] = 0x55555555L ;
+        pVideoMemory[ 6 ] = 0xAAAAAAAAL ;
+        pVideoMemory[ 7 ] = 0xAAAAAAAAL ;
+
+        if ( pVideoMemory[ 1 ] == 0x456789ABL )
+        {
+            if ( pVideoMemory[ 0 ] == 0x01234567L )
+            {
+                /* Channel A 64bit */
+                return ;
+            }
+        }
+        else
+        {
+            if ( pVideoMemory[ 0 ] == 0x01234567L )
+            {
+                /* Channel A 32bit */
+                XGINew_DataBusWidth = 32 ;
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x00 ) ;
+                return ;
+            }
+        }
+
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x03 ) ;        /* Channel B, 64bit */
+        XGINew_DDR_MRS( pVBInfo);
+
+        XGINew_ChannelAB = 1 ;
+        XGINew_DataBusWidth = 64 ;
+        pVideoMemory[ 0 ] = 0x01234567L ;
+        pVideoMemory[ 1 ] = 0x456789ABL ;
+        pVideoMemory[ 2 ] = 0x89ABCDEFL ;
+        pVideoMemory[ 3 ] = 0xCDEF0123L ;
+        pVideoMemory[ 4 ] = 0x55555555L ;
+        pVideoMemory[ 5 ] = 0x55555555L ;
+        pVideoMemory[ 6 ] = 0xAAAAAAAAL ;
+        pVideoMemory[ 7 ] = 0xAAAAAAAAL ;
+
+        if ( pVideoMemory[ 1 ] == 0x456789ABL )
+        {
+            /* Channel B 64 */
+            if ( pVideoMemory[ 0 ] == 0x01234567L )
+            {
+                /* Channel B 64bit */
+                return ;
+            }
+            else
+            {
+                /* error */
+            }
+        }
+        else
+        {
+            if ( pVideoMemory[ 0 ] == 0x01234567L )
+            {
+                /* Channel B 32 */
+                XGINew_DataBusWidth = 32 ;
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x01 ) ;
+            }
+            else
+            {
+                /* error */
+            }
+        }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetRank */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_SetRank( int index , UCHAR RankNo , UCHAR XGINew_ChannelAB , USHORT DRAMTYPE_TABLE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT data ;
+    int RankSize ;
+
+    if ( ( RankNo == 2 ) && ( DRAMTYPE_TABLE[ index ][ 0 ] == 2 ) )
+        return 0 ;
+
+    RankSize = DRAMTYPE_TABLE[ index ][ 3 ] / 2 * XGINew_DataBusWidth / 32 ;
+
+    if ( ( RankNo * RankSize ) <= 128 )
+    {
+        data = 0 ;
+
+        while( ( RankSize >>= 1 ) > 0 )
+        {
+            data += 0x10 ;
+        }
+        data |= ( RankNo - 1 ) << 2 ;
+        data |= ( XGINew_DataBusWidth / 64 ) & 2 ;
+        data |= XGINew_ChannelAB ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ;
+        /* should delay */
+        XGINew_SDR_MRS( pVBInfo ) ;
+        return( 1 ) ;
+    }
+    else
+        return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDDRChannel */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_SetDDRChannel( int index , UCHAR ChannelNo , UCHAR XGINew_ChannelAB , USHORT DRAMTYPE_TABLE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT  data ;
+    int RankSize ;
+
+    RankSize = DRAMTYPE_TABLE[index][3]/2 * XGINew_DataBusWidth/32;
+    /* RankSize = DRAMTYPE_TABLE[ index ][ 3 ] ; */
+    if ( ChannelNo * RankSize <= 128 )
+    {
+        data = 0 ;
+        while( ( RankSize >>= 1 ) > 0 )
+        {
+            data += 0x10 ;
+        }
+
+        if ( ChannelNo == 2 )
+            data |= 0x0C ;
+
+        data |= ( XGINew_DataBusWidth / 32 ) & 2 ;
+        data |= XGINew_ChannelAB ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ;
+        /* should delay */
+        XGINew_DDR_MRS( pVBInfo ) ;
+        return( 1 ) ;
+    }
+    else
+        return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckColumn */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckColumn( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+    int i ;
+    ULONG Increment , Position ;
+
+    /* Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + XGINew_DataBusWidth / 64 + 1 ) ; */
+    Increment = 1 << ( 10 + XGINew_DataBusWidth / 64 ) ;
+
+    for( i = 0 , Position = 0 ; i < 2 ; i++ )
+    {
+        *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+        Position += Increment ;
+    }
+
+#ifdef WIN2000  /* chiawen for linux solution */
+    DelayUS( 100 ) ;
+#endif
+
+    for( i = 0 , Position = 0 ; i < 2 ; i++ )
+    {
+        /* if ( pVBInfo->FBAddr[ Position ] != Position ) */
+        if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+            return( 0 ) ;
+        Position += Increment ;
+    }
+    return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckBanks */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckBanks( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+    int i ;
+    ULONG Increment , Position ;
+
+    Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + XGINew_DataBusWidth / 64 + 2 ) ;
+
+    for( i = 0 , Position = 0 ; i < 4 ; i++ )
+    {
+        /* pVBInfo->FBAddr[ Position ] = Position ; */
+        *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+        Position += Increment ;
+    }
+
+    for( i = 0 , Position = 0 ; i < 4 ; i++ )
+    {
+        /* if (pVBInfo->FBAddr[ Position ] != Position ) */
+        if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+            return( 0 ) ;
+        Position += Increment ;
+    }
+    return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckRank */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+    int i ;
+    ULONG Increment , Position ;
+
+    Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + DRAMTYPE_TABLE[ index ][ 1 ] +
+                  DRAMTYPE_TABLE[ index ][ 0 ] + XGINew_DataBusWidth / 64 + RankNo ) ;
+
+    for( i = 0 , Position = 0 ; i < 2 ; i++ )
+    {
+        /* pVBInfo->FBAddr[ Position ] = Position ; */
+        /* *( ( PULONG )( pVBInfo->FBAddr ) ) = Position ; */
+        *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+        Position += Increment ;
+    }
+
+    for( i = 0 , Position = 0 ; i < 2 ; i++ )
+    {
+        /* if ( pVBInfo->FBAddr[ Position ] != Position ) */
+        /* if ( ( *( PULONG )( pVBInfo->FBAddr ) ) != Position ) */
+        if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+            return( 0 ) ;
+        Position += Increment ;
+    }
+    return( 1 );
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckDDRRank */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckDDRRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+    ULONG Increment , Position ;
+    USHORT data ;
+
+    Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + DRAMTYPE_TABLE[ index ][ 1 ] +
+                       DRAMTYPE_TABLE[ index ][ 0 ] + XGINew_DataBusWidth / 64 + RankNo ) ;
+
+    Increment += Increment / 2 ;
+
+    Position = 0;
+    *( ( PULONG )( pVBInfo->FBAddr + Position + 0 ) ) = 0x01234567 ;
+    *( ( PULONG )( pVBInfo->FBAddr + Position + 1 ) ) = 0x456789AB ;
+    *( ( PULONG )( pVBInfo->FBAddr + Position + 2 ) ) = 0x55555555 ;
+    *( ( PULONG )( pVBInfo->FBAddr + Position + 3 ) ) = 0x55555555 ;
+    *( ( PULONG )( pVBInfo->FBAddr + Position + 4 ) ) = 0xAAAAAAAA ;
+    *( ( PULONG )( pVBInfo->FBAddr + Position + 5 ) ) = 0xAAAAAAAA ;
+
+    if ( ( *( PULONG )( pVBInfo->FBAddr + 1 ) ) == 0x456789AB )
+        return( 1 ) ;
+
+    if ( ( *( PULONG )( pVBInfo->FBAddr + 0 ) ) == 0x01234567 )
+        return( 0 ) ;
+
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
+    data &= 0xF3 ;
+    data |= 0x0E ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ;
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x15 ) ;
+    data += 0x20 ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , data ) ;
+
+    return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckRanks */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckRanks( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+    int r ;
+
+    for( r = RankNo ; r >= 1 ; r-- )
+    {
+        if ( !XGINew_CheckRank( r , index , DRAMTYPE_TABLE, pVBInfo ) )
+            return( 0 ) ;
+    }
+
+    if ( !XGINew_CheckBanks( index , DRAMTYPE_TABLE, pVBInfo ) )
+        return( 0 ) ;
+
+    if ( !XGINew_CheckColumn( index , DRAMTYPE_TABLE, pVBInfo ) )
+        return( 0 ) ;
+
+    return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckDDRRanks */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckDDRRanks( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+    int r ;
+
+    for( r = RankNo ; r >= 1 ; r-- )
+    {
+        if ( !XGINew_CheckDDRRank( r , index , DRAMTYPE_TABLE, pVBInfo ) )
+            return( 0 ) ;
+    }
+
+    if ( !XGINew_CheckBanks( index , DRAMTYPE_TABLE, pVBInfo ) )
+        return( 0 ) ;
+
+    if ( !XGINew_CheckColumn( index , DRAMTYPE_TABLE, pVBInfo ) )
+        return( 0 ) ;
+
+    return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_SDRSizing(PVB_DEVICE_INFO pVBInfo)
+{
+    int    i ;
+    UCHAR  j ;
+
+    for( i = 0 ; i < 13 ; i++ )
+    {
+        XGINew_SetDRAMSizingType( i , XGINew_SDRDRAM_TYPE , pVBInfo) ;
+
+        for( j = 2 ; j > 0 ; j-- )
+        {
+            if ( !XGINew_SetRank( i , ( UCHAR )j , XGINew_ChannelAB , XGINew_SDRDRAM_TYPE , pVBInfo) )
+                continue ;
+            else
+            {
+                if ( XGINew_CheckRanks( j , i , XGINew_SDRDRAM_TYPE, pVBInfo) )
+                    return( 1 ) ;
+            }
+        }
+    }
+    return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMSizeReg */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGINew_SetDRAMSizeReg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT data = 0 , memsize = 0 ;
+    int RankSize ;
+    UCHAR ChannelNo ;
+
+    RankSize = DRAMTYPE_TABLE[ index ][ 3 ] * XGINew_DataBusWidth / 32 ;
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x13 ) ;
+    data &= 0x80 ;
+
+    if ( data == 0x80 )
+        RankSize *= 2 ;
+
+    data = 0 ;
+
+    if( XGINew_ChannelAB == 3 )
+        ChannelNo = 4 ;
+    else
+        ChannelNo = XGINew_ChannelAB ;
+
+    if ( ChannelNo * RankSize <= 256 )
+    {
+        while( ( RankSize >>= 1 ) > 0 )
+        {
+            data += 0x10 ;
+        }
+
+        memsize = data >> 4 ;
+
+        /* [2004/03/25] Vicent, Fix DRAM Sizing Error */
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) & 0x0F ) | ( data & 0xF0 ) ) ;
+
+       /* data |= XGINew_ChannelAB << 2 ; */
+       /* data |= ( XGINew_DataBusWidth / 64 ) << 1 ; */
+       /* XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ; */
+
+        /* should delay */
+        /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */
+    }
+    return( memsize ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMSize20Reg */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGINew_SetDRAMSize20Reg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT data = 0 , memsize = 0 ;
+    int RankSize ;
+    UCHAR ChannelNo ;
+
+    RankSize = DRAMTYPE_TABLE[ index ][ 3 ] * XGINew_DataBusWidth / 8 ;
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x13 ) ;
+    data &= 0x80 ;
+
+    if ( data == 0x80 )
+        RankSize *= 2 ;
+
+    data = 0 ;
+
+    if( XGINew_ChannelAB == 3 )
+        ChannelNo = 4 ;
+    else
+        ChannelNo = XGINew_ChannelAB ;
+
+    if ( ChannelNo * RankSize <= 256 )
+    {
+        while( ( RankSize >>= 1 ) > 0 )
+        {
+            data += 0x10 ;
+        }
+
+        memsize = data >> 4 ;
+
+        /* [2004/03/25] Vicent, Fix DRAM Sizing Error */
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) & 0x0F ) | ( data & 0xF0 ) ) ;
+       DelayUS( 15 ) ;
+
+       /* data |= XGINew_ChannelAB << 2 ; */
+       /* data |= ( XGINew_DataBusWidth / 64 ) << 1 ; */
+       /* XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ; */
+
+        /* should delay */
+        /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */
+    }
+    return( memsize ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_ReadWriteRest */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_ReadWriteRest( USHORT StopAddr , USHORT StartAddr, PVB_DEVICE_INFO pVBInfo)
+{
+    int i ;
+    ULONG Position = 0 ;
+
+   *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+
+    for( i = StartAddr ; i <= StopAddr ; i++ )
+    {
+        Position = 1 << i ;
+        *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+    }
+
+    DelayUS( 500 ) ;   /* [Vicent] 2004/04/16. Fix #1759 Memory Size error in Multi-Adapter. */
+
+    Position = 0 ;
+
+   if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+        return( 0 ) ;
+
+    for( i = StartAddr ; i <= StopAddr ; i++ )
+    {
+        Position = 1 << i ;
+        if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+            return( 0 ) ;
+    }
+    return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckFrequence */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGINew_CheckFrequence( PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR data ;
+
+    data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) ;
+
+    if ( ( data & 0x10 ) == 0 )
+    {
+        data = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) ;
+        data = ( data & 0x02 ) >> 1 ;
+        return( data ) ;
+    }
+    else
+        return( data & 0x01 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckChannel */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_CheckChannel( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR data;
+
+    switch( HwDeviceExtension->jChipType )
+    {
+      case XG20:
+      case XG21:
+          data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) ;
+          data = data & 0x01;
+          XGINew_ChannelAB = 1 ;               /* XG20 "JUST" one channel */
+
+          if ( data == 0 )  /* Single_32_16 */
+          {
+
+             if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x1000000)
+             {
+
+                XGINew_DataBusWidth = 32 ;     /* 32 bits */
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ;  /* 22bit + 2 rank + 32bit */
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ;
+               DelayUS( 15 ) ;
+
+                if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+                    return ;
+
+               if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000)
+               {
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ;  /* 22bit + 1 rank + 32bit */
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ;
+                 DelayUS( 15 ) ;
+
+                  if ( XGINew_ReadWriteRest( 23 , 23 , pVBInfo ) == 1 )
+                      return ;
+                }
+             }
+
+             if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000)
+             {
+               XGINew_DataBusWidth = 16 ;      /* 16 bits */
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ;  /* 22bit + 2 rank + 16bit */
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x41 ) ;
+               DelayUS( 15 ) ;
+
+                if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
+                    return ;
+                else
+                    XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ;
+                    DelayUS( 15 ) ;
+              }
+
+          }
+          else  /* Dual_16_8 */
+          {
+              if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000)
+              {
+
+                XGINew_DataBusWidth = 16 ;     /* 16 bits */
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ;  /* (0x31:12x8x2) 22bit + 2 rank */
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x41 ) ;  /* 0x41:16Mx16 bit*/
+                DelayUS( 15 ) ;
+
+                if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
+                    return ;
+
+               if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x400000)
+               {
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ;  /* (0x31:12x8x2) 22bit + 1 rank */
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x31 ) ;  /* 0x31:8Mx16 bit*/
+                  DelayUS( 15 ) ;
+
+                  if ( XGINew_ReadWriteRest( 22 , 22 , pVBInfo ) == 1 )
+                      return ;
+                }
+             }
+
+
+             if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x400000)
+             {
+               XGINew_DataBusWidth = 8 ;       /* 8 bits */
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ;  /* (0x31:12x8x2) 22bit + 2 rank */
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x30 ) ;  /* 0x30:8Mx8 bit*/
+                DelayUS( 15 ) ;
+
+                if ( XGINew_ReadWriteRest( 22 , 21 , pVBInfo ) == 1 )
+                    return ;
+                else
+                    XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ;  /* (0x31:12x8x2) 22bit + 1 rank */
+                    DelayUS( 15 ) ;
+              }
+          }
+          break ;
+
+      case XG27:
+          XGINew_DataBusWidth = 16 ;   /* 16 bits */
+          XGINew_ChannelAB = 1 ;               /* Single channel */
+          XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x51 ) ;  /* 32Mx16 bit*/
+          break ;
+      case XG41:
+          if ( XGINew_CheckFrequence(pVBInfo) == 1 )
+          {
+              XGINew_DataBusWidth = 32 ;       /* 32 bits */
+              XGINew_ChannelAB = 3 ;           /* Quad Channel */
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4C ) ;
+
+              if ( XGINew_ReadWriteRest( 25 , 23 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_ChannelAB = 2 ;           /* Dual channels */
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x48 ) ;
+
+              if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x49 ) ;
+
+              if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_ChannelAB = 3 ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x3C ) ;
+
+              if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x38 ) ;
+
+              if ( XGINew_ReadWriteRest( 8 , 4 , pVBInfo ) == 1 )
+                  return ;
+              else
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x39 ) ;
+          }
+          else
+          {                                    /* DDR */
+              XGINew_DataBusWidth = 64 ;       /* 64 bits */
+              XGINew_ChannelAB = 2 ;           /* Dual channels */
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x5A ) ;
+
+              if ( XGINew_ReadWriteRest( 25 , 24 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_ChannelAB = 1 ;           /* Single channels */
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ;
+
+              if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x53 ) ;
+
+              if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_ChannelAB = 2 ;           /* Dual channels */
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4A ) ;
+
+              if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_ChannelAB = 1 ;           /* Single channels */
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ;
+
+              if ( XGINew_ReadWriteRest( 8 , 4 , pVBInfo ) == 1 )
+                  return ;
+              else
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x43 ) ;
+          }
+
+          break ;
+
+      case XG42:
+/*
+         XG42 SR14 D[3] Reserve
+                   D[2] = 1, Dual Channel
+                        = 0, Single Channel
+
+         It's Different from Other XG40 Series.
+*/
+          if ( XGINew_CheckFrequence(pVBInfo) == 1 )   /* DDRII, DDR2x */
+          {
+              XGINew_DataBusWidth = 32 ;       /* 32 bits */
+              XGINew_ChannelAB = 2 ;           /* 2 Channel */
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x44 ) ;
+
+              if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x34 ) ;
+              if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_ChannelAB = 1 ;           /* Single Channel */
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x40 ) ;
+
+              if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
+                  return ;
+              else
+              {
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x30 ) ;
+              }
+          }
+          else
+          {                                    /* DDR */
+              XGINew_DataBusWidth = 64 ;       /* 64 bits */
+              XGINew_ChannelAB = 1 ;           /* 1 channels */
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ;
+
+              if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+                  return ;
+              else
+              {
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ;
+              }
+          }
+
+          break ;
+
+      default: /* XG40 */
+
+          if ( XGINew_CheckFrequence(pVBInfo) == 1 )   /* DDRII */
+          {
+              XGINew_DataBusWidth = 32 ;       /* 32 bits */
+              XGINew_ChannelAB = 3 ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4C ) ;
+
+              if ( XGINew_ReadWriteRest( 25 , 23 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_ChannelAB = 2 ;           /* 2 channels */
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x48 ) ;
+
+              if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+                  return ;
+
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x3C ) ;
+
+              if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+                  XGINew_ChannelAB = 3 ;       /* 4 channels */
+              else
+              {
+                  XGINew_ChannelAB = 2 ;       /* 2 channels */
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x38 ) ;
+              }
+          }
+          else
+          {                                    /* DDR */
+              XGINew_DataBusWidth = 64 ;       /* 64 bits */
+              XGINew_ChannelAB = 2 ;           /* 2 channels */
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+              XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x5A ) ;
+
+              if ( XGINew_ReadWriteRest( 25 , 24 , pVBInfo ) == 1 )
+                  return ;
+              else
+              {
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+                  XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4A ) ;
+              }
+          }
+         break ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDRSizing340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+    int i ;
+    USHORT memsize , addr ;
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , 0x00 ) ;    /* noninterleaving */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x1C , 0x00 ) ;    /* nontiling */
+    XGINew_CheckChannel( HwDeviceExtension, pVBInfo ) ;
+
+
+    if ( HwDeviceExtension->jChipType >= XG20 )
+    {
+      for( i = 0 ; i < 12 ; i++ )
+      {
+        XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE20, pVBInfo ) ;
+        memsize = XGINew_SetDRAMSize20Reg( i , XGINew_DDRDRAM_TYPE20, pVBInfo ) ;
+        if ( memsize == 0 )
+            continue ;
+
+        addr = memsize + ( XGINew_ChannelAB - 2 ) + 20 ;
+        if ( ( HwDeviceExtension->ulVideoMemorySize - 1 ) < ( ULONG )( 1 << addr ) )
+            continue ;
+
+        if ( XGINew_ReadWriteRest( addr , 5, pVBInfo ) == 1 )
+            return( 1 ) ;
+      }
+    }
+    else
+    {
+      for( i = 0 ; i < 4 ; i++ )
+      {
+       XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE340, pVBInfo ) ;
+        memsize = XGINew_SetDRAMSizeReg( i , XGINew_DDRDRAM_TYPE340, pVBInfo ) ;
+
+        if ( memsize == 0 )
+            continue ;
+
+        addr = memsize + ( XGINew_ChannelAB - 2 ) + 20 ;
+        if ( ( HwDeviceExtension->ulVideoMemorySize - 1 ) < ( ULONG )( 1 << addr ) )
+            continue ;
+
+        if ( XGINew_ReadWriteRest( addr , 9, pVBInfo ) == 1 )
+            return( 1 ) ;
+      }
+    }
+    return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDRSizing */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_DDRSizing(PVB_DEVICE_INFO pVBInfo)
+{
+    int    i ;
+    UCHAR  j ;
+
+    for( i = 0 ; i < 4 ; i++ )
+    {
+        XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE, pVBInfo ) ;
+        XGINew_DisableChannelInterleaving( i , XGINew_DDRDRAM_TYPE , pVBInfo) ;
+        for( j = 2 ; j > 0 ; j-- )
+        {
+            XGINew_SetDDRChannel( i , j , XGINew_ChannelAB , XGINew_DDRDRAM_TYPE , pVBInfo ) ;
+            if ( !XGINew_SetRank( i , ( UCHAR )j , XGINew_ChannelAB , XGINew_DDRDRAM_TYPE, pVBInfo ) )
+                continue ;
+            else
+            {
+                if ( XGINew_CheckDDRRanks( j , i , XGINew_DDRDRAM_TYPE,  pVBInfo ) )
+                return( 1 ) ;
+            }
+        }
+    }
+    return( 0 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetMemoryClock */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetMemoryClock( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x28 , pVBInfo->MCLKData[ XGINew_RAMType ].SR28 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x29 , pVBInfo->MCLKData[ XGINew_RAMType ].SR29 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2A , pVBInfo->MCLKData[ XGINew_RAMType ].SR2A ) ;
+
+
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , pVBInfo->ECLKData[ XGINew_RAMType ].SR2E ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , pVBInfo->ECLKData[ XGINew_RAMType ].SR2F ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x30 , pVBInfo->ECLKData[ XGINew_RAMType ].SR30 ) ;
+
+    /* [Vicent] 2004/07/07, When XG42 ECLK = MCLK = 207MHz, Set SR32 D[1:0] = 10b */
+    /* [Hsuan] 2004/08/20, Modify SR32 value, when MCLK=207MHZ, ELCK=250MHz, Set SR32 D[1:0] = 10b */
+    if ( HwDeviceExtension->jChipType == XG42 )
+    {
+      if ( ( pVBInfo->MCLKData[ XGINew_RAMType ].SR28 == 0x1C ) && ( pVBInfo->MCLKData[ XGINew_RAMType ].SR29 == 0x01 )
+        && ( ( ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2E == 0x1C ) && ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2F == 0x01 ) )
+        || ( ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2E == 0x22 ) && ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2F == 0x01 ) ) ) )
+      {
+       XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , ( ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) & 0xFC ) | 0x02 ) ;
+      }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : ChkLFB */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN ChkLFB( PVB_DEVICE_INFO pVBInfo )
+{
+    if ( LFBDRAMTrap & XGINew_GetReg1( pVBInfo->P3d4 , 0x78 ) )
+        return( TRUE ) ;
+    else
+        return( FALSE );
+}
+
+
+/* --------------------------------------------------------------------- */
+/* input : dx ,valid value : CR or second chip's CR */
+/*  */
+/* SetPowerConsume : */
+/* Description: reduce 40/43 power consumption in first chip or */
+/* in second chip, assume CR A1 D[6]="1" in this case */
+/* output : none */
+/* --------------------------------------------------------------------- */
+void SetPowerConsume ( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG XGI_P3d4Port )
+{
+    ULONG   lTemp ;
+    UCHAR   bTemp;
+
+    HwDeviceExtension->pQueryVGAConfigSpace( HwDeviceExtension , 0x08 , 0 , &lTemp ) ; /* Get */
+    if ((lTemp&0xFF)==0)
+    {
+        /* set CR58 D[5]=0 D[3]=0 */
+        XGINew_SetRegAND( XGI_P3d4Port , 0x58 , 0xD7 ) ;
+        bTemp = (UCHAR) XGINew_GetReg1( XGI_P3d4Port , 0xCB ) ;
+       if (bTemp&0x20)
+       {
+            if (!(bTemp&0x10))
+            {
+               XGINew_SetRegANDOR( XGI_P3d4Port , 0x58 , 0xD7 , 0x20 ) ; /* CR58 D[5]=1 D[3]=0 */
+            }
+            else
+            {
+               XGINew_SetRegANDOR( XGI_P3d4Port , 0x58 , 0xD7 , 0x08 ) ; /* CR58 D[5]=0 D[3]=1 */
+            }
+
+       }
+
+    }
+}
+
+
+
+#if defined(LINUX_XF86)||defined(LINUX_KERNEL)
+void XGINew_InitVBIOSData(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+
+       /* ULONG ROMAddr = (ULONG)HwDeviceExtension->pjVirtualRomBase; */
+    pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+    pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+    pVBInfo->ISXPDOS = 0 ;
+
+    pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+    pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+    pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+    pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+    pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+    pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+    pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+    pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+    pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+    pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+    pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+    pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+    pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+    pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+    pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+    pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+    pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+    if ( HwDeviceExtension->jChipType < XG20 )                  /* kuku 2004/06/25 */
+    XGI_GetVBType( pVBInfo ) ;         /* Run XGI_GetVBType before InitTo330Pointer */
+
+       switch(HwDeviceExtension->jChipType)
+       {
+       case XG40:
+       case XG41:
+       case XG42:
+       case XG20:
+       case XG21:
+       default:
+               InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
+               return ;
+       }
+
+}
+#endif /* For Linux */
+
+/* --------------------------------------------------------------------- */
+/* Function : ReadVBIOSTablData */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo)
+{
+    PUCHAR  volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
+    ULONG   i ;
+    UCHAR   j , k ;
+#if 0
+    ULONG   ii , jj ;
+    i = pVideoMemory[ 0x1CF ] | ( pVideoMemory[ 0x1D0 ] << 8 ) ;               /* UniROM */
+    if ( i != 0 )
+        UNIROM = 1 ;
+
+    ii = 0x90 ;
+    for( jj = 0x00 ; jj < 0x08 ; jj++ )
+    {
+        pVBInfo->MCLKData[ jj ].SR28 = pVideoMemory[ ii ] ;
+        pVBInfo->MCLKData[ jj ].SR29 = pVideoMemory[ ii + 1] ;
+        pVBInfo->MCLKData[ jj ].SR2A = pVideoMemory[ ii + 2] ;
+        pVBInfo->MCLKData[ jj ].CLOCK = pVideoMemory[ ii + 3 ] | ( pVideoMemory[ ii + 4 ] << 8 ) ;
+        ii += 0x05 ;
+    }
+
+    ii = 0xB8 ;
+    for( jj = 0x00 ; jj < 0x08 ; jj++ )
+    {
+        pVBInfo->ECLKData[ jj ].SR2E = pVideoMemory[ ii ] ;
+        pVBInfo->ECLKData[ jj ].SR2F=pVideoMemory[ ii + 1 ] ;
+        pVBInfo->ECLKData[ jj ].SR30= pVideoMemory[ ii + 2 ] ;
+        pVBInfo->ECLKData[ jj ].CLOCK= pVideoMemory[ ii + 3 ] | ( pVideoMemory[ ii + 4 ] << 8 ) ;
+        ii += 0x05 ;
+    }
+
+    /* Volari customize data area start */
+    /* if ( ChipType == XG40 ) */
+    if ( ChipType >= XG40 )
+    {
+        ii = 0xE0 ;
+        for( jj = 0x00 ; jj < 0x03 ; jj++ )
+        {
+            pVBInfo->SR15[ jj ][ 0 ] = pVideoMemory[ ii ] ;            /* SR13, SR14, and SR18 */
+            pVBInfo->SR15[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+            pVBInfo->SR15[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+            pVBInfo->SR15[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+            pVBInfo->SR15[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+            pVBInfo->SR15[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+            pVBInfo->SR15[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+            pVBInfo->SR15[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+            ii += 0x08 ;
+        }
+        ii = 0x110 ;
+        jj = 0x03 ;
+        pVBInfo->SR15[ jj ][ 0 ] = pVideoMemory[ ii ] ;                /* SR1B */
+        pVBInfo->SR15[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+        pVBInfo->SR15[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+        pVBInfo->SR15[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+        pVBInfo->SR15[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+        pVBInfo->SR15[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+        pVBInfo->SR15[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+        pVBInfo->SR15[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+
+        *pVBInfo->pSR07 = pVideoMemory[ 0x74 ] ;
+        *pVBInfo->pSR1F = pVideoMemory[ 0x75 ] ;
+        *pVBInfo->pSR21 = pVideoMemory[ 0x76 ] ;
+        *pVBInfo->pSR22 = pVideoMemory[ 0x77 ] ;
+        *pVBInfo->pSR23 = pVideoMemory[ 0x78 ] ;
+        *pVBInfo->pSR24 = pVideoMemory[ 0x79 ] ;
+        pVBInfo->SR25[ 0 ] = pVideoMemory[ 0x7A ] ;
+        *pVBInfo->pSR31 = pVideoMemory[ 0x7B ] ;
+        *pVBInfo->pSR32 = pVideoMemory[ 0x7C ] ;
+        *pVBInfo->pSR33 = pVideoMemory[ 0x7D ] ;
+        ii = 0xF8 ;
+
+        for( jj = 0 ; jj < 3 ; jj++ )
+        {
+            pVBInfo->CR40[ jj ][ 0 ] = pVideoMemory[ ii ] ;
+            pVBInfo->CR40[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+            pVBInfo->CR40[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+            pVBInfo->CR40[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+            pVBInfo->CR40[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+            pVBInfo->CR40[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+            pVBInfo->CR40[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+            pVBInfo->CR40[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+            ii += 0x08 ;
+        }
+
+        ii = 0x118 ;
+        for( j = 3 ; j < 24 ; j++ )
+        {
+            pVBInfo->CR40[ j ][ 0 ] = pVideoMemory[ ii ] ;
+            pVBInfo->CR40[ j ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+            pVBInfo->CR40[ j ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+            pVBInfo->CR40[ j ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+            pVBInfo->CR40[ j ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+            pVBInfo->CR40[ j ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+            pVBInfo->CR40[ j ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+            pVBInfo->CR40[ j ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+            ii += 0x08 ;
+        }
+
+        i = pVideoMemory[ 0x1C0 ] | ( pVideoMemory[ 0x1C1 ] << 8 ) ;
+
+        for( j = 0 ; j < 8 ; j++ )
+        {
+            for( k = 0 ; k < 4 ; k++ )
+                pVBInfo->CR6B[ j ][ k ] = pVideoMemory[ i + 4 * j + k ] ;
+        }
+
+        i = pVideoMemory[ 0x1C2 ] | ( pVideoMemory[ 0x1C3 ] << 8 ) ;
+
+        for( j = 0 ; j < 8 ; j++ )
+        {
+            for( k = 0 ; k < 4 ; k++ )
+                pVBInfo->CR6E[ j ][ k ] = pVideoMemory[ i + 4 * j + k ] ;
+        }
+
+        i = pVideoMemory[ 0x1C4 ] | ( pVideoMemory[ 0x1C5 ] << 8 ) ;
+        for( j = 0 ; j < 8 ; j++ )
+        {
+            for( k = 0 ; k < 32 ; k++ )
+                pVBInfo->CR6F[ j ][ k ] = pVideoMemory[ i + 32 * j + k ] ;
+        }
+
+        i = pVideoMemory[ 0x1C6 ] | ( pVideoMemory[ 0x1C7 ] << 8 ) ;
+
+        for( j = 0 ; j < 8 ; j++ )
+        {
+            for( k = 0 ; k < 2 ; k++ )
+                pVBInfo->CR89[ j ][ k ] = pVideoMemory[ i + 2 * j + k ] ;
+        }
+
+        i = pVideoMemory[ 0x1C8 ] | ( pVideoMemory[ 0x1C9 ] << 8 ) ;
+        for( j = 0 ; j < 12 ; j++ )
+            pVBInfo->AGPReg[ j ] = pVideoMemory[ i + j ] ;
+
+        i = pVideoMemory[ 0x1CF ] | ( pVideoMemory[ 0x1D0 ] << 8 ) ;
+        for( j = 0 ; j < 4 ; j++ )
+            pVBInfo->SR16[ j ] = pVideoMemory[ i + j ] ;
+
+        if ( ChipType == XG21 )
+        {
+            if (pVideoMemory[ 0x67 ] & 0x80)
+            {
+                *pVBInfo->pDVOSetting = pVideoMemory[ 0x67 ];
+            }
+            if ( (pVideoMemory[ 0x67 ] & 0xC0) == 0xC0 )
+            {
+                *pVBInfo->pCR2E = pVideoMemory[ i + 4 ] ;
+                *pVBInfo->pCR2F = pVideoMemory[ i + 5 ] ;
+                *pVBInfo->pCR46 = pVideoMemory[ i + 6 ] ;
+                *pVBInfo->pCR47 = pVideoMemory[ i + 7 ] ;
+            }
+        }
+
+        if ( ChipType == XG27 )
+        {
+            jj = i+j;
+            for( i = 0 ; i <= 0xB ; i++,jj++ )
+              pVBInfo->pCRD0[i] = pVideoMemory[ jj ] ;
+            for( i = 0x0 ; i <= 0x1 ; i++,jj++ )
+              pVBInfo->pCRDE[i] = pVideoMemory[ jj ] ;
+
+            *pVBInfo->pSR40 = pVideoMemory[ jj ] ;
+            jj++;
+            *pVBInfo->pSR41 = pVideoMemory[ jj ] ;
+
+            if (pVideoMemory[ 0x67 ] & 0x80)
+            {
+                *pVBInfo->pDVOSetting = pVideoMemory[ 0x67 ];
+            }
+            if ( (pVideoMemory[ 0x67 ] & 0xC0) == 0xC0 )
+            {
+                jj++;
+                *pVBInfo->pCR2E = pVideoMemory[ jj ] ;
+                *pVBInfo->pCR2F = pVideoMemory[ jj + 1 ] ;
+                *pVBInfo->pCR46 = pVideoMemory[ jj + 2 ] ;
+                *pVBInfo->pCR47 = pVideoMemory[ jj + 3 ] ;
+            }
+
+        }
+
+        *pVBInfo->pCRCF = pVideoMemory[ 0x1CA ] ;
+        *pVBInfo->pXGINew_DRAMTypeDefinition = pVideoMemory[ 0x1CB ] ;
+        *pVBInfo->pXGINew_I2CDefinition = pVideoMemory[ 0x1D1 ] ;
+        if ( ChipType >= XG20 )
+        {
+           *pVBInfo->pXGINew_CR97 = pVideoMemory[ 0x1D2 ] ;
+           if ( ChipType == XG27 )
+           {
+             *pVBInfo->pSR36 = pVideoMemory[ 0x1D3 ] ;
+             *pVBInfo->pCR8F = pVideoMemory[ 0x1D5 ] ;
+           }
+        }
+
+    }
+#endif
+    /* Volari customize data area end */
+
+    if ( ChipType == XG21 )
+    {
+        pVBInfo->IF_DEF_LVDS = 0 ;
+        if (pVideoMemory[ 0x65 ] & 0x1)
+        {
+            pVBInfo->IF_DEF_LVDS = 1 ;
+            i = pVideoMemory[ 0x316 ] | ( pVideoMemory[ 0x317 ] << 8 );
+            j = pVideoMemory[ i-1 ] ;
+            if ( j != 0xff )
+            {
+              k = 0;
+              do
+              {
+                pVBInfo->XG21_LVDSCapList[k].LVDS_Capability = pVideoMemory[ i ] | ( pVideoMemory[ i + 1 ] << 8 );
+                pVBInfo->XG21_LVDSCapList[k].LVDSHT = pVideoMemory[ i + 2 ] | ( pVideoMemory[ i + 3 ] << 8 ) ;
+                pVBInfo->XG21_LVDSCapList[k].LVDSVT = pVideoMemory[ i + 4 ] | ( pVideoMemory[ i + 5 ] << 8 );
+                pVBInfo->XG21_LVDSCapList[k].LVDSHDE = pVideoMemory[ i + 6 ] | ( pVideoMemory[ i + 7 ] << 8 );
+                pVBInfo->XG21_LVDSCapList[k].LVDSVDE = pVideoMemory[ i + 8 ] | ( pVideoMemory[ i + 9 ] << 8 );
+                pVBInfo->XG21_LVDSCapList[k].LVDSHFP = pVideoMemory[ i + 10 ] | ( pVideoMemory[ i + 11 ] << 8 );
+                pVBInfo->XG21_LVDSCapList[k].LVDSVFP = pVideoMemory[ i + 12 ] | ( pVideoMemory[ i + 13 ] << 8 );
+                pVBInfo->XG21_LVDSCapList[k].LVDSHSYNC = pVideoMemory[ i + 14 ] | ( pVideoMemory[ i + 15 ] << 8 );
+                pVBInfo->XG21_LVDSCapList[k].LVDSVSYNC = pVideoMemory[ i + 16 ] | ( pVideoMemory[ i + 17 ] << 8 );
+                pVBInfo->XG21_LVDSCapList[k].VCLKData1 = pVideoMemory[ i + 18 ] ;
+                pVBInfo->XG21_LVDSCapList[k].VCLKData2 = pVideoMemory[ i + 19 ] ;
+                pVBInfo->XG21_LVDSCapList[k].PSC_S1 = pVideoMemory[ i + 20 ] ;
+                pVBInfo->XG21_LVDSCapList[k].PSC_S2 = pVideoMemory[ i + 21 ] ;
+                pVBInfo->XG21_LVDSCapList[k].PSC_S3 = pVideoMemory[ i + 22 ] ;
+                pVBInfo->XG21_LVDSCapList[k].PSC_S4 = pVideoMemory[ i + 23 ] ;
+                pVBInfo->XG21_LVDSCapList[k].PSC_S5 = pVideoMemory[ i + 24 ] ;
+                i += 25;
+                j--;
+                k++;
+              } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) );
+            }
+            else
+            {
+            pVBInfo->XG21_LVDSCapList[0].LVDS_Capability = pVideoMemory[ i ] | ( pVideoMemory[ i + 1 ] << 8 );
+            pVBInfo->XG21_LVDSCapList[0].LVDSHT = pVideoMemory[ i + 2 ] | ( pVideoMemory[ i + 3 ] << 8 ) ;
+            pVBInfo->XG21_LVDSCapList[0].LVDSVT = pVideoMemory[ i + 4 ] | ( pVideoMemory[ i + 5 ] << 8 );
+            pVBInfo->XG21_LVDSCapList[0].LVDSHDE = pVideoMemory[ i + 6 ] | ( pVideoMemory[ i + 7 ] << 8 );
+            pVBInfo->XG21_LVDSCapList[0].LVDSVDE = pVideoMemory[ i + 8 ] | ( pVideoMemory[ i + 9 ] << 8 );
+            pVBInfo->XG21_LVDSCapList[0].LVDSHFP = pVideoMemory[ i + 10 ] | ( pVideoMemory[ i + 11 ] << 8 );
+            pVBInfo->XG21_LVDSCapList[0].LVDSVFP = pVideoMemory[ i + 12 ] | ( pVideoMemory[ i + 13 ] << 8 );
+            pVBInfo->XG21_LVDSCapList[0].LVDSHSYNC = pVideoMemory[ i + 14 ] | ( pVideoMemory[ i + 15 ] << 8 );
+            pVBInfo->XG21_LVDSCapList[0].LVDSVSYNC = pVideoMemory[ i + 16 ] | ( pVideoMemory[ i + 17 ] << 8 );
+            pVBInfo->XG21_LVDSCapList[0].VCLKData1 = pVideoMemory[ i + 18 ] ;
+            pVBInfo->XG21_LVDSCapList[0].VCLKData2 = pVideoMemory[ i + 19 ] ;
+            pVBInfo->XG21_LVDSCapList[0].PSC_S1 = pVideoMemory[ i + 20 ] ;
+            pVBInfo->XG21_LVDSCapList[0].PSC_S2 = pVideoMemory[ i + 21 ] ;
+            pVBInfo->XG21_LVDSCapList[0].PSC_S3 = pVideoMemory[ i + 22 ] ;
+            pVBInfo->XG21_LVDSCapList[0].PSC_S4 = pVideoMemory[ i + 23 ] ;
+            pVBInfo->XG21_LVDSCapList[0].PSC_S5 = pVideoMemory[ i + 24 ] ;
+        }
+        }
+    }
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR1x_MRS_XG20 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR1x_MRS_XG20( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ;
+    XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+    DelayUS( 60 ) ;
+
+    XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;
+    XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+    DelayUS( 60 ) ;
+    XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ;     /* SR18 */
+    /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x03 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ;
+    DelayUS( 1000 ) ;
+    XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ;
+    DelayUS( 500 ) ;
+    /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
+    XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ;     /* SR18 */
+    XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x03 ) ;
+    XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ;
+    XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMModeRegister_XG20 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+    VB_DEVICE_INFO VBINF;
+    PVB_DEVICE_INFO pVBInfo = &VBINF;
+    pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+    pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+    pVBInfo->ISXPDOS = 0 ;
+
+    pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+    pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+    pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+    pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+    pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+    pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+    pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+    pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+    pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+    pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+    pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+    pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+    pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+    pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+    pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+    pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+    pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+    InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
+
+    ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+
+    if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
+        XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ;
+    else
+        XGINew_DDR2_MRS_XG20( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ;
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
+}
+
+void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+    VB_DEVICE_INFO VBINF;
+    PVB_DEVICE_INFO pVBInfo = &VBINF;
+    pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+    pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+    pVBInfo->ISXPDOS = 0 ;
+
+    pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+    pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+    pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+    pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+    pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+    pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+    pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+    pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+    pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+    pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+    pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+    pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+    pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+    pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+    pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+    pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+    pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+    InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
+
+    ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+
+    if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
+        XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ;
+    else
+        //XGINew_DDR2_MRS_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ;
+        XGINew_DDRII_Bootup_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo) ;
+
+    //XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ;    /* SR1B */
+
+}
+/*
+void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+#ifndef LINUX_XF86
+    UCHAR data ;
+#endif
+    VB_DEVICE_INFO VBINF;
+    PVB_DEVICE_INFO pVBInfo = &VBINF;
+    pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+    pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+    pVBInfo->BaseAddr = HwDeviceExtension->pjIOAddress ;
+    pVBInfo->ISXPDOS = 0 ;
+
+    pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+    pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+    pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+    pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+    pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+    pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+    pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+    pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+    pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+    pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+    pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+    pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+    pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+    pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+    pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+    pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+    pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+    InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
+
+    ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+
+    if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
+        XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ;
+    else
+        XGINew_DDR2_MRS_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ;
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
+}
+*/
+/* -------------------------------------------------------- */
+/* Function : XGINew_ChkSenseStatus */
+/* Input : */
+/* Output : */
+/* Description : */
+/* -------------------------------------------------------- */
+void XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempbx=0 , temp , tempcx , CR3CData;
+
+    temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x32 ) ;
+
+    if ( temp & Monitor1Sense )
+       tempbx |= ActiveCRT1 ;
+    if ( temp & LCDSense )
+       tempbx |= ActiveLCD ;
+    if ( temp & Monitor2Sense )
+       tempbx |= ActiveCRT2 ;
+    if ( temp & TVSense )
+    {
+       tempbx |= ActiveTV ;
+       if ( temp & AVIDEOSense )
+           tempbx |= ( ActiveAVideo << 8 );
+       if ( temp & SVIDEOSense )
+           tempbx |= ( ActiveSVideo << 8 );
+       if ( temp & SCARTSense )
+           tempbx |= ( ActiveSCART << 8 );
+       if ( temp & HiTVSense )
+           tempbx |= ( ActiveHiTV << 8 );
+       if ( temp & YPbPrSense )
+           tempbx |= ( ActiveYPbPr << 8 );
+    }
+
+    tempcx = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ;
+    tempcx |= ( XGINew_GetReg1( pVBInfo->P3d4 , 0x3e ) << 8 ) ;
+
+    if ( tempbx & tempcx )
+    {
+       CR3CData = XGINew_GetReg1( pVBInfo->P3d4 , 0x3c ) ;
+       if ( !( CR3CData & DisplayDeviceFromCMOS ) )
+       {
+           tempcx = 0x1FF0 ;
+           if ( *pVBInfo->pSoftSetting & ModeSoftSetting )
+           {
+               tempbx = 0x1FF0 ;
+           }
+       }
+    }
+    else
+    {
+       tempcx = 0x1FF0 ;
+       if ( *pVBInfo->pSoftSetting & ModeSoftSetting )
+       {
+           tempbx = 0x1FF0 ;
+       }
+    }
+
+    tempbx &= tempcx ;
+    XGINew_SetReg1( pVBInfo->P3d4, 0x3d , ( tempbx & 0x00FF ) ) ;
+    XGINew_SetReg1( pVBInfo->P3d4, 0x3e , ( ( tempbx & 0xFF00 ) >> 8 )) ;
+}
+/* -------------------------------------------------------- */
+/* Function : XGINew_SetModeScratch */
+/* Input : */
+/* Output : */
+/* Description : */
+/* -------------------------------------------------------- */
+void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT temp , tempcl = 0 , tempch = 0 , CR31Data , CR38Data;
+
+    temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ;
+    temp |= XGINew_GetReg1( pVBInfo->P3d4 , 0x3e ) << 8 ;
+    temp |= ( XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) & ( DriverMode >> 8) ) << 8 ;
+
+    if ( pVBInfo->IF_DEF_CRT2Monitor == 1)
+    {
+       if ( temp & ActiveCRT2 )
+          tempcl = SetCRT2ToRAMDAC ;
+    }
+
+    if ( temp & ActiveLCD )
+    {
+       tempcl |= SetCRT2ToLCD ;
+       if  ( temp & DriverMode )
+       {
+           if ( temp & ActiveTV )
+           {
+               tempch = SetToLCDA | EnableDualEdge ;
+               temp ^= SetCRT2ToLCD ;
+
+               if ( ( temp >> 8 ) & ActiveAVideo )
+                   tempcl |= SetCRT2ToAVIDEO ;
+               if ( ( temp >> 8 ) & ActiveSVideo )
+                   tempcl |= SetCRT2ToSVIDEO ;
+               if ( ( temp >> 8 ) & ActiveSCART )
+                   tempcl |= SetCRT2ToSCART ;
+
+               if ( pVBInfo->IF_DEF_HiVision == 1 )
+               {
+                   if ( ( temp >> 8 ) & ActiveHiTV )
+                   tempcl |= SetCRT2ToHiVisionTV ;
+               }
+
+               if ( pVBInfo->IF_DEF_YPbPr == 1 )
+               {
+                   if ( ( temp >> 8 ) & ActiveYPbPr )
+                   tempch |= SetYPbPr ;
+               }
+           }
+       }
+    }
+    else
+    {
+       if ( ( temp >> 8 ) & ActiveAVideo )
+          tempcl |= SetCRT2ToAVIDEO ;
+       if ( ( temp >> 8 ) & ActiveSVideo )
+          tempcl |= SetCRT2ToSVIDEO ;
+       if ( ( temp >> 8 ) & ActiveSCART )
+          tempcl |= SetCRT2ToSCART ;
+
+       if ( pVBInfo->IF_DEF_HiVision == 1 )
+       {
+          if ( ( temp >> 8 ) & ActiveHiTV )
+          tempcl |= SetCRT2ToHiVisionTV ;
+       }
+
+       if ( pVBInfo->IF_DEF_YPbPr == 1 )
+       {
+          if ( ( temp >> 8 ) & ActiveYPbPr )
+          tempch |= SetYPbPr ;
+       }
+    }
+
+
+    tempcl |= SetSimuScanMode ;
+    if ( (!( temp & ActiveCRT1 )) && ( ( temp & ActiveLCD ) || ( temp & ActiveTV ) || ( temp & ActiveCRT2 ) ) )
+       tempcl ^= ( SetSimuScanMode | SwitchToCRT2 ) ;
+    if ( ( temp & ActiveLCD ) && ( temp & ActiveTV ) )
+       tempcl ^= ( SetSimuScanMode | SwitchToCRT2 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4, 0x30 , tempcl ) ;
+
+    CR31Data = XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ;
+    CR31Data &= ~( SetNotSimuMode >> 8 ) ;
+    if ( !( temp & ActiveCRT1 ) )
+        CR31Data |= ( SetNotSimuMode >> 8 ) ;
+    CR31Data &= ~( DisableCRT2Display >> 8 ) ;
+    if  (!( ( temp & ActiveLCD ) || ( temp & ActiveTV ) || ( temp & ActiveCRT2 ) ) )
+        CR31Data |= ( DisableCRT2Display >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4, 0x31 , CR31Data ) ;
+
+    CR38Data = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+    CR38Data &= ~SetYPbPr ;
+    CR38Data |= tempch ;
+    XGINew_SetReg1( pVBInfo->P3d4, 0x38 , CR38Data ) ;
+
+}
+
+/* -------------------------------------------------------- */
+/* Function : XGINew_GetXG21Sense */
+/* Input : */
+/* Output : */
+/* Description : */
+/* -------------------------------------------------------- */
+void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR Temp;
+    PUCHAR  volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
+
+    pVBInfo->IF_DEF_LVDS = 0 ;
+
+#ifdef WIN2000
+   pVBInfo->IF_DEF_CH7007 = 0 ;
+    if ( ( pVideoMemory[ 0x65 ] & 0x02 ) )                     /* For XG21 CH7007 */
+    {
+        /* VideoDebugPrint((0, "ReadVBIOSTablData: pVideoMemory[ 0x65 ] =%x\n",pVideoMemory[ 0x65 ])); */
+        pVBInfo->IF_DEF_CH7007 = 1 ;                            /* [Billy] 07/05/03 */
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0x60 ) ; /* CH7007 on chip */
+    }
+    else
+#endif
+#if 1
+    if (( pVideoMemory[ 0x65 ] & 0x01 ) )                      /* For XG21 LVDS */
+    {
+        pVBInfo->IF_DEF_LVDS = 1 ;
+        XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ;
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xC0 ) ; /* LVDS on chip */
+    }
+    else
+    {
+#endif
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x03 , 0x03 ) ; /* Enable GPIOA/B read  */
+        Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0xC0;
+        if ( Temp == 0xC0 )
+        {                                                              /* DVI & DVO GPIOA/B pull high */
+          XGINew_SenseLCD( HwDeviceExtension, pVBInfo ) ;
+          XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ;
+          XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x20 , 0x20 ) ;   /* Enable read GPIOF */
+          Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0x04 ;
+          if ( !Temp )
+            XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0x80 ) ; /* TMDS on chip */
+          else
+            XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xA0 ) ; /* Only DVO on chip */
+          XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ;       /* Disable read GPIOF */
+        }
+#if 1
+    }
+#endif
+}
+
+/* -------------------------------------------------------- */
+/* Function : XGINew_GetXG27Sense */
+/* Input : */
+/* Output : */
+/* Description : */
+/* -------------------------------------------------------- */
+void XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR Temp,bCR4A;
+
+     pVBInfo->IF_DEF_LVDS = 0 ;
+     bCR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+     XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x07 , 0x07 ) ; /* Enable GPIOA/B/C read  */
+     Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0x07;
+     XGINew_SetReg1( pVBInfo->P3d4, 0x4A , bCR4A ) ;
+
+     if ( Temp <= 0x02 )
+     {
+         pVBInfo->IF_DEF_LVDS = 1 ;
+         XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xC0 ) ; /* LVDS setting */
+         XGINew_SetReg1( pVBInfo->P3d4, 0x30 , 0x21 ) ;
+     }
+     else
+     {
+       XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xA0 ) ; /* TMDS/DVO setting */
+     }
+     XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ;
+
+}
+
+UCHAR GetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR CR38,CR4A,temp;
+
+    CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x10 , 0x10 ) ; /* enable GPIOE read */
+    CR38 = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+    temp =0;
+    if ( ( CR38 & 0xE0 ) > 0x80 )
+    {
+        temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
+        temp &= 0x08;
+        temp >>= 3;
+    }
+
+    XGINew_SetReg1( pVBInfo->P3d4, 0x4A , CR4A ) ;
+
+    return temp;
+}
+
+UCHAR GetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR CR4A,temp;
+
+    CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x03 , 0x03 ) ; /* enable GPIOA/B/C read */
+    temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
+    if ( temp <= 2 )
+    {
+       temp &= 0x03;
+    }
+    else
+    {
+       temp = ((temp&0x04)>>1) || ((~temp)&0x01);
+    }
+    XGINew_SetReg1( pVBInfo->P3d4, 0x4A , CR4A ) ;
+
+    return temp;
+}
+
diff --git a/drivers/staging/xgifb/vb_init.h b/drivers/staging/xgifb/vb_init.h
new file mode 100644 (file)
index 0000000..1f39d9c
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef  _VBINIT_
+#define  _VBINIT_
+extern   BOOLEAN    XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension ) ;
+extern XGI21_LVDSCapStruct  XGI21_LCDCapList[13];
+
+#endif
+
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
new file mode 100644 (file)
index 0000000..bd7f738
--- /dev/null
@@ -0,0 +1,10736 @@
+#include "osdef.h"
+
+#ifdef TC
+#include <stdio.h>
+#include <string.h>
+#include <conio.h>
+#include <dos.h>
+#endif
+
+
+#ifdef LINUX_XF86
+#include "xf86.h"
+#include "xf86PciInfo.h"
+#include "xgi.h"
+#include "xgi_regs.h"
+#endif
+
+#ifdef LINUX_KERNEL
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include "XGIfb.h"
+/*#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <video/XGIfb.h>
+#else
+#include <linux/XGIfb.h>
+#endif*/
+#endif
+
+#ifdef WIN2000
+#include <dderror.h>
+#include <devioctl.h>
+#include <miniport.h>
+#include <ntddvdeo.h>
+#include <video.h>
+
+#include "xgiv.h"
+#include "dd_i2c.h"
+#include "tools.h"
+#endif
+
+#include "vb_def.h"
+#include "vgatypes.h"
+#include "vb_struct.h"
+#include "vb_util.h"
+#include "vb_table.h"
+
+
+
+#define  IndexMask 0xff
+#ifndef XGI_MASK_DUAL_CHIP
+#define XGI_MASK_DUAL_CHIP       0x04  /* SR3A */
+#endif
+
+
+
+BOOLEAN  XGI_IsLCDDualLink(PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGI_SetCRT2Group301(USHORT ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo);
+
+BOOLEAN  XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGI_AjustCRT2Rate(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,USHORT *i, PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGI_SearchModeID( USHORT ModeNo,USHORT  *ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGI_GetLCDInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ) ;
+BOOLEAN  XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo);
+UCHAR    XGI_GetModePtr( USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+USHORT   XGI_GetOffset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+USHORT   XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
+USHORT   XGI_GetResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+USHORT   XGI_GetColorDepth(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+USHORT   XGI_GetVGAHT2(PVB_DEVICE_INFO pVBInfo);
+USHORT   XGI_GetVCLK2Ptr(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+void     XGI_VBLongWait(PVB_DEVICE_INFO pVBInfo);
+void     XGI_SaveCRT2Info(USHORT ModeNo, PVB_DEVICE_INFO pVBInfo);
+void     XGI_GetCRT2Data(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_GetCRT2ResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_PreSetGroup1(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetGroup1(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetLockRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetLCDRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetGroup2(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetGroup3(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetGroup5(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void*    XGI_GetLcdPtr(USHORT BX,  USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void*    XGI_GetTVPtr(USHORT BX, USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void    XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo);
+void    XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void    XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void    XGI_SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+void    XGI_SetPanelPower(USHORT tempah,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+void    XGI_EnablePWD( PVB_DEVICE_INFO pVBInfo);
+void    XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo);
+void     XGI_AutoThreshold( PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo);
+
+void     XGI_DisplayOn(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+void     XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
+void     XGI_SetCRT1Group(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo);
+void     XGI_SetXG27CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo);
+void    XGI_UpdateXG21CRTC(USHORT ModeNo, PVB_DEVICE_INFO pVBInfo, USHORT RefreshRateTableIndex);
+void     XGI_WaitDisply(PVB_DEVICE_INFO pVBInfo);
+void     XGI_SenseCRT1(PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetSeqRegs(USHORT ModeNo,USHORT StandTableIndex,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetMiscRegs(USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetATTRegs(USHORT ModeNo,USHORT StandTableIndex,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
+void     XGI_SetGRCRegs(USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo);
+
+void     XGI_SetSync(USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetCRT1CRTC(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension);
+void     XGI_SetCRT1Timing_H(PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension);
+void     XGI_SetCRT1Timing_V(USHORT ModeIdIndex,USHORT ModeNo,PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetCRT1VCLK(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetCRT1FIFO(USHORT ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetCRT1ModeRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetVCLKState(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+
+void     XGI_LoadDAC(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+void     XGI_WriteDAC(USHORT dl, USHORT ah, USHORT al, USHORT dh, PVB_DEVICE_INFO pVBInfo);
+/*void     XGI_ClearBuffer(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,PVB_DEVICE_INFO pVBInfo);*/
+void     XGI_SetLCDAGroup(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+void     XGI_GetLVDSResInfo( USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO  pVBInfo);
+void     XGI_GetLVDSData(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+void     XGI_ModCRT1Regs(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+void     XGI_SetLVDSRegs(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+void     XGI_UpdateModeInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+void     XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+void     XGI_GetVBType(PVB_DEVICE_INFO  pVBInfo);
+void     XGI_GetVBInfo(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+void     XGI_GetTVInfo(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO  pVBInfo);
+void     XGI_SetCRT2ECLK( USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+void     InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo);
+void     XGI_GetLCDSync(USHORT* HSyncWidth, USHORT* VSyncWidth, PVB_DEVICE_INFO pVBInfo);
+void    XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void    XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetCRT2VCLK(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_OEM310Setting(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetDelayComp(PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetLCDCap(PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetLCDCap_A(USHORT tempcx,PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetLCDCap_B(USHORT tempcx,PVB_DEVICE_INFO pVBInfo);
+void     SetSpectrum(PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetAntiFlicker(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetEdgeEnhance(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetPhaseIncr(PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetYFilter(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_GetTVPtrIndex2(USHORT* tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo);
+USHORT   XGI_GetTVPtrIndex(  PVB_DEVICE_INFO pVBInfo );
+void     XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
+void     XGI_CloseCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+void     XGI_OpenCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+void     XGI_GetRAMDAC2DATA(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+void     XGI_LockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+void     XGINew_EnableCRT2(PVB_DEVICE_INFO pVBInfo);
+void     XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo);
+void     XGI_LongWait(PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetCRT1Offset( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo );
+void     XGI_GetLCDVCLKPtr(UCHAR* di_0,UCHAR *di_1, PVB_DEVICE_INFO pVBInfo);
+UCHAR    XGI_GetVCLKPtr(USHORT RefreshRateTableIndex,USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void     XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInfo);
+USHORT   XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo);
+USHORT   XGI_GetLCDCapPtr1(PVB_DEVICE_INFO pVBInfo);
+XGI301C_Tap4TimingStruct* XGI_GetTap4Ptr(USHORT tempcx, PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+void     XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+UCHAR    XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo);
+UCHAR    XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo);
+void     XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+void     XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+void     XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+BOOLEAN  XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+void     XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+void     XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+UCHAR    XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo );
+
+extern   void    ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
+#ifdef WIN2000
+/* [Billy] 2007/05/17 For CH7007 */
+extern  UCHAR CH7007TVReg_UNTSC[][8],CH7007TVReg_ONTSC[][8],CH7007TVReg_UPAL[][8],CH7007TVReg_OPAL[][8];
+extern  UCHAR CH7007TVCRT1UNTSC_H[][10],CH7007TVCRT1ONTSC_H[][10],CH7007TVCRT1UPAL_H[][10],CH7007TVCRT1OPAL_H[][10] ;
+extern  UCHAR CH7007TVCRT1UNTSC_V[][10],CH7007TVCRT1ONTSC_V[][10],CH7007TVCRT1UPAL_V[][10],CH7007TVCRT1OPAL_V[][10] ;
+extern  UCHAR XGI7007_CHTVVCLKUNTSC[],XGI7007_CHTVVCLKONTSC[],XGI7007_CHTVVCLKUPAL[],XGI7007_CHTVVCLKOPAL[];
+
+extern  BOOLEAN XGI_XG21CheckCH7007TVMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) ;
+extern  void SetCH7007Regs(PXGI_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO  pVBInfo ) ;
+extern  VP_STATUS TurnOnCH7007(PHW_DEVICE_EXTENSION pHWDE) ;
+extern  VP_STATUS TurnOffCH7007(PHW_DEVICE_EXTENSION pHWDE) ;
+extern  BOOLEAN IsCH7007TVMode(PVB_DEVICE_INFO pVBInfo) ;
+#endif
+
+/* USHORT XGINew_flag_clearbuffer; 0: no clear frame buffer 1:clear frame buffer */
+
+
+
+
+
+USHORT XGINew_MDA_DAC[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+               0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+               0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+               0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F};
+
+USHORT XGINew_CGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+               0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+               0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+               0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
+
+USHORT XGINew_EGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
+               0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
+               0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
+               0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
+               0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
+               0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
+               0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
+
+USHORT XGINew_VGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+               0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
+               0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
+
+               0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
+               0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
+               0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
+               0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
+               0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
+               0x0B,0x0C,0x0D,0x0F,0x10};
+
+
+/* --------------------------------------------------------------------- */
+/* Function : InitTo330Pointer */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void InitTo330Pointer( UCHAR ChipType ,PVB_DEVICE_INFO pVBInfo)
+{
+    pVBInfo->SModeIDTable = (XGI_StStruct *) XGI330_SModeIDTable ;
+    pVBInfo->StandTable = (XGI_StandTableStruct *) XGI330_StandTable ;
+    pVBInfo->EModeIDTable = (XGI_ExtStruct *) XGI330_EModeIDTable ;
+    pVBInfo->RefIndex = (XGI_Ext2Struct *) XGI330_RefIndex ;
+    pVBInfo->XGINEWUB_CRT1Table = (XGI_CRT1TableStruct *) XGI_CRT1Table ;
+
+    /* add for new UNIVGABIOS */
+    /* XGINew_UBLCDDataTable = (XGI_LCDDataTablStruct *) XGI_LCDDataTable ; */
+    /* XGINew_UBTVDataTable = (XGI_TVDataTablStruct *) XGI_TVDataTable ; */
+
+
+    if ( ChipType >= XG40 )
+    {
+        pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI340New_MCLKData ;
+        pVBInfo->ECLKData = (XGI_ECLKDataStruct *) XGI340_ECLKData ;
+    }
+    else
+    {
+        pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI330New_MCLKData ;
+        pVBInfo->ECLKData = (XGI_ECLKDataStruct *) XGI330_ECLKData ;
+    }
+
+    pVBInfo->VCLKData = (XGI_VCLKDataStruct *) XGI_VCLKData ;
+    pVBInfo->VBVCLKData = (XGI_VBVCLKDataStruct *) XGI_VBVCLKData ;
+    pVBInfo->ScreenOffset = XGI330_ScreenOffset ;
+    pVBInfo->StResInfo = (XGI_StResInfoStruct *) XGI330_StResInfo ;
+    pVBInfo->ModeResInfo = (XGI_ModeResInfoStruct *) XGI330_ModeResInfo ;
+
+    pVBInfo->pOutputSelect = &XGI330_OutputSelect ;
+    pVBInfo->pSoftSetting = &XGI330_SoftSetting ;
+    pVBInfo->pSR07 = &XGI330_SR07 ;
+    pVBInfo->LCDResInfo = 0 ;
+    pVBInfo->LCDTypeInfo = 0 ;
+    pVBInfo->LCDInfo = 0 ;
+    pVBInfo->VBInfo = 0 ;
+    pVBInfo->TVInfo = 0;
+
+
+    pVBInfo->SR15 = XGI340_SR13 ;
+    pVBInfo->CR40 = XGI340_cr41 ;
+    pVBInfo->SR25 = XGI330_sr25 ;
+    pVBInfo->pSR31 = &XGI330_sr31 ;
+    pVBInfo->pSR32 = &XGI330_sr32 ;
+    pVBInfo->CR6B = XGI340_CR6B ;
+    pVBInfo->CR6E = XGI340_CR6E ;
+    pVBInfo->CR6F = XGI340_CR6F ;
+    pVBInfo->CR89 = XGI340_CR89 ;
+    pVBInfo->AGPReg = XGI340_AGPReg ;
+    pVBInfo->SR16 = XGI340_SR16 ;
+    pVBInfo->pCRCF = &XG40_CRCF ;
+    pVBInfo->pXGINew_DRAMTypeDefinition = &XG40_DRAMTypeDefinition ;
+
+
+    pVBInfo->CR49 = XGI330_CR49 ;
+    pVBInfo->pSR1F = &XGI330_SR1F ;
+    pVBInfo->pSR21 = &XGI330_SR21 ;
+    pVBInfo->pSR22 = &XGI330_SR22 ;
+    pVBInfo->pSR23 = &XGI330_SR23 ;
+    pVBInfo->pSR24 = &XGI330_SR24 ;
+    pVBInfo->pSR33 = &XGI330_SR33 ;
+
+
+
+    pVBInfo->pCRT2Data_1_2 = &XGI330_CRT2Data_1_2 ;
+    pVBInfo->pCRT2Data_4_D = &XGI330_CRT2Data_4_D ;
+    pVBInfo->pCRT2Data_4_E = &XGI330_CRT2Data_4_E ;
+    pVBInfo->pCRT2Data_4_10 = &XGI330_CRT2Data_4_10 ;
+    pVBInfo->pRGBSenseData = &XGI330_RGBSenseData ;
+    pVBInfo->pVideoSenseData = &XGI330_VideoSenseData ;
+    pVBInfo->pYCSenseData = &XGI330_YCSenseData ;
+    pVBInfo->pRGBSenseData2 = &XGI330_RGBSenseData2 ;
+    pVBInfo->pVideoSenseData2 = &XGI330_VideoSenseData2 ;
+    pVBInfo->pYCSenseData2 = &XGI330_YCSenseData2 ;
+
+    pVBInfo->NTSCTiming = XGI330_NTSCTiming ;
+    pVBInfo->PALTiming = XGI330_PALTiming ;
+    pVBInfo->HiTVExtTiming = XGI330_HiTVExtTiming ;
+    pVBInfo->HiTVSt1Timing = XGI330_HiTVSt1Timing ;
+    pVBInfo->HiTVSt2Timing = XGI330_HiTVSt2Timing ;
+    pVBInfo->HiTVTextTiming = XGI330_HiTVTextTiming ;
+    pVBInfo->YPbPr750pTiming = XGI330_YPbPr750pTiming ;
+    pVBInfo->YPbPr525pTiming = XGI330_YPbPr525pTiming ;
+    pVBInfo->YPbPr525iTiming = XGI330_YPbPr525iTiming ;
+    pVBInfo->HiTVGroup3Data = XGI330_HiTVGroup3Data ;
+    pVBInfo->HiTVGroup3Simu = XGI330_HiTVGroup3Simu ;
+    pVBInfo->HiTVGroup3Text = XGI330_HiTVGroup3Text ;
+    pVBInfo->Ren525pGroup3 = XGI330_Ren525pGroup3 ;
+    pVBInfo->Ren750pGroup3 = XGI330_Ren750pGroup3 ;
+
+
+    pVBInfo->TimingH = (XGI_TimingHStruct *) XGI_TimingH ;
+    pVBInfo->TimingV = (XGI_TimingVStruct *) XGI_TimingV ;
+    pVBInfo->UpdateCRT1 = (XGI_XG21CRT1Struct *) XGI_UpdateCRT1Table ;
+
+    pVBInfo->CHTVVCLKUNTSC = XGI330_CHTVVCLKUNTSC ;
+    pVBInfo->CHTVVCLKONTSC = XGI330_CHTVVCLKONTSC ;
+    pVBInfo->CHTVVCLKUPAL = XGI330_CHTVVCLKUPAL ;
+    pVBInfo->CHTVVCLKOPAL = XGI330_CHTVVCLKOPAL ;
+
+    /* 310 customization related */
+    if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+        pVBInfo->LCDCapList = XGI_LCDDLCapList ;
+    else
+        pVBInfo->LCDCapList = XGI_LCDCapList ;
+
+    if ( ( ChipType == XG21 ) || ( ChipType == XG27 ) )
+        pVBInfo->XG21_LVDSCapList = XGI21_LCDCapList ;
+
+    pVBInfo->XGI_TVDelayList = XGI301TVDelayList ;
+    pVBInfo->XGI_TVDelayList2 = XGI301TVDelayList2 ;
+
+
+    pVBInfo->pXGINew_I2CDefinition = &XG40_I2CDefinition ;
+
+    if ( ChipType >= XG20 )
+       pVBInfo->pXGINew_CR97 = &XG20_CR97 ;
+
+    if ( ChipType == XG27 )
+    {
+        pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI27New_MCLKData ;
+        pVBInfo->CR40 = XGI27_cr41 ;
+       pVBInfo->pXGINew_CR97 = &XG27_CR97 ;
+       pVBInfo->pSR36 = &XG27_SR36 ;
+       pVBInfo->pCR8F = &XG27_CR8F ;
+       pVBInfo->pCRD0 = XG27_CRD0 ;
+       pVBInfo->pCRDE = XG27_CRDE ;
+       pVBInfo->pSR40 = &XG27_SR40 ;
+       pVBInfo->pSR41 = &XG27_SR41 ;
+
+    }
+
+    if ( ChipType >= XG20 )
+    {
+       pVBInfo->pDVOSetting = &XG21_DVOSetting ;
+       pVBInfo->pCR2E = &XG21_CR2E ;
+       pVBInfo->pCR2F = &XG21_CR2F ;
+       pVBInfo->pCR46 = &XG21_CR46 ;
+       pVBInfo->pCR47 = &XG21_CR47 ;
+    }
+
+}
+
+
+
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGISetModeNew */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo )
+{
+    USHORT ModeIdIndex ;
+        /* PUCHAR pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; */
+    VB_DEVICE_INFO VBINF;
+    PVB_DEVICE_INFO pVBInfo = &VBINF;
+    pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+    pVBInfo->IF_DEF_LVDS = 0 ;
+    pVBInfo->IF_DEF_CH7005 = 0 ;
+    pVBInfo->IF_DEF_LCDA = 1 ;
+    pVBInfo->IF_DEF_CH7017 = 0 ;
+    pVBInfo->IF_DEF_CH7007 = 0 ;                                /* [Billy] 2007/05/14 */
+    pVBInfo->IF_DEF_VideoCapture = 0 ;
+    pVBInfo->IF_DEF_ScaleLCD = 0 ;
+    pVBInfo->IF_DEF_OEMUtil = 0 ;
+    pVBInfo->IF_DEF_PWD = 0 ;
+
+
+    if ( HwDeviceExtension->jChipType >= XG20 )                        /* kuku 2004/06/25 */
+    {
+       pVBInfo->IF_DEF_YPbPr = 0 ;
+        pVBInfo->IF_DEF_HiVision = 0 ;
+        pVBInfo->IF_DEF_CRT2Monitor = 0 ;
+        pVBInfo->VBType = 0 ;  /*set VBType default 0*/
+    }
+    else if ( HwDeviceExtension->jChipType >= XG40 )
+    {
+        pVBInfo->IF_DEF_YPbPr = 1 ;
+        pVBInfo->IF_DEF_HiVision = 1 ;
+        pVBInfo->IF_DEF_CRT2Monitor = 1 ;
+    }
+    else
+    {
+        pVBInfo->IF_DEF_YPbPr = 1 ;
+        pVBInfo->IF_DEF_HiVision = 1 ;
+        pVBInfo->IF_DEF_CRT2Monitor = 0 ;
+    }
+
+    pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+    pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+    pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+    pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+    pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+    pVBInfo->P3cc = pVBInfo->BaseAddr + 0x1C ;
+    pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+    pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+    pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+    pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+    pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+    pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+    pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+    pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+    pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+    pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+    pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+    pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+    if ( HwDeviceExtension->jChipType == XG21 )  /* for x86 Linux, XG21 LVDS */
+    {
+        if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 )
+        {
+            pVBInfo->IF_DEF_LVDS = 1 ;
+        }
+    }
+    if ( HwDeviceExtension->jChipType == XG27 )
+    {
+        if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 )
+        {
+          if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) & 0x20 )
+          {
+            pVBInfo->IF_DEF_LVDS = 1 ;
+          }
+        }
+    }
+
+    if ( HwDeviceExtension->jChipType < XG20 )                 /* kuku 2004/06/25 */
+    XGI_GetVBType( pVBInfo ) ;
+
+    InitTo330Pointer( HwDeviceExtension->jChipType, pVBInfo ) ;
+#ifdef WIN2000
+    ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+#endif
+    if ( ModeNo & 0x80 )
+    {
+        ModeNo = ModeNo & 0x7F ;
+/* XGINew_flag_clearbuffer = 0 ; */
+    }
+/*    else
+    {
+        XGINew_flag_clearbuffer = 1 ;
+    }
+*/
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
+
+    if ( HwDeviceExtension->jChipType < XG20 )                 /* kuku 2004/06/25 1.Openkey */
+    XGI_UnLockCRT2( HwDeviceExtension , pVBInfo ) ;
+
+    XGI_SearchModeID( ModeNo , &ModeIdIndex, pVBInfo ) ;
+
+    XGI_GetVGAType(HwDeviceExtension,  pVBInfo) ;
+
+    if ( HwDeviceExtension->jChipType < XG20 )                 /* kuku 2004/06/25 */
+    {
+        XGI_GetVBInfo(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
+        XGI_GetTVInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
+        XGI_GetLCDInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
+        XGI_DisableBridge( HwDeviceExtension,pVBInfo ) ;
+/*        XGI_OpenCRTC( HwDeviceExtension, pVBInfo ) ; */
+
+        if ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToLCDA ) )
+        {
+            XGI_SetCRT1Group(HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
+
+            if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+            {
+                XGI_SetLCDAGroup(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
+            }
+        }
+        else
+        {
+            if ( !( pVBInfo->VBInfo & SwitchToCRT2) )
+            {
+                XGI_SetCRT1Group( HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
+                if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+                {
+                    XGI_SetLCDAGroup( ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
+                }
+            }
+        }
+
+        if ( pVBInfo->VBInfo & ( SetSimuScanMode | SwitchToCRT2 ) )
+        {
+            switch( HwDeviceExtension->ujVBChipID )
+            {
+                case VB_CHIP_301:
+                    XGI_SetCRT2Group301( ModeNo , HwDeviceExtension, pVBInfo ) ;               /*add for CRT2 */
+                    break ;
+
+                case VB_CHIP_302:
+                    XGI_SetCRT2Group301(ModeNo , HwDeviceExtension, pVBInfo ) ;                /*add for CRT2 */
+                    break ;
+
+                default:
+                    break ;
+            }
+        }
+
+        XGI_SetCRT2ModeRegs( ModeNo, HwDeviceExtension,pVBInfo ) ;
+        XGI_OEM310Setting( ModeNo, ModeIdIndex,pVBInfo ) ; /*0212*/
+        XGI_CloseCRTC( HwDeviceExtension, pVBInfo ) ;
+        XGI_EnableBridge( HwDeviceExtension ,pVBInfo) ;
+    }  /* !XG20 */
+    else
+    {
+#ifdef WIN2000
+        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+        {
+
+            VideoDebugPrint((0, "XGISetModeNew: pVBIfo->IF_DEF_CH7007==1\n"));
+            pVBInfo->VBType = VB_CH7007 ;
+            XGI_GetVBInfo(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
+            XGI_GetTVInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
+            XGI_GetLCDInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
+            if( !(XGI_XG21CheckCH7007TVMode(ModeNo, ModeIdIndex, pVBInfo )) )
+            {
+              return FALSE;
+            }
+        }
+#endif
+
+
+        if ( pVBInfo->IF_DEF_LVDS == 1 )
+        {
+            if ( !XGI_XG21CheckLVDSMode(ModeNo , ModeIdIndex, pVBInfo) )
+            {
+              return FALSE;
+            }
+        }
+
+        if ( ModeNo <= 0x13 )
+        {
+            pVBInfo->ModeType = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag & ModeInfoFlag;
+        }
+        else
+        {
+            pVBInfo->ModeType = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag & ModeInfoFlag;
+        }
+
+       pVBInfo->SetFlag = 0 ;
+        if ( pVBInfo->IF_DEF_CH7007 != 1 )
+        {
+           pVBInfo->VBInfo = DisableCRT2Display ;
+        }
+
+
+       XGI_DisplayOff(HwDeviceExtension, pVBInfo) ;
+
+       XGI_SetCRT1Group(HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
+
+       XGI_DisplayOn( HwDeviceExtension, pVBInfo ) ;
+       /*
+       if( HwDeviceExtension->jChipType == XG21 )
+         XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ;
+       */
+    }
+
+
+/*
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+    }
+    pVBInfo->ModeType = modeflag&ModeInfoFlag ;
+    pVBInfo->SetFlag = 0x00 ;
+    pVBInfo->VBInfo = DisableCRT2Display ;
+    temp = XGINew_CheckMemorySize(  HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
+
+    if ( temp == 0 )
+        return( 0 ) ;
+
+    XGI_DisplayOff( HwDeviceExtension, pVBInfo) ;
+    XGI_SetCRT1Group( HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
+    XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
+*/
+
+    XGI_UpdateModeInfo( HwDeviceExtension, pVBInfo ) ;
+
+    if ( HwDeviceExtension->jChipType < XG20 )                 /* kuku 2004/06/25 */
+{
+    XGI_LockCRT2( HwDeviceExtension, pVBInfo ) ;
+}
+
+    return( TRUE ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1Group */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1Group( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT StandTableIndex ,
+           RefreshRateTableIndex ,
+           b3CC ,
+           temp ;
+
+    USHORT XGINew_P3cc =  pVBInfo->P3cc;
+
+    /* XGINew_CRT1Mode = ModeNo ; // SaveModeID */
+    StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
+    /* XGI_SetBIOSData(ModeNo , ModeIdIndex ) ; */
+    /* XGI_ClearBankRegs( ModeNo , ModeIdIndex ) ; */
+    XGI_SetSeqRegs( ModeNo , StandTableIndex , ModeIdIndex, pVBInfo ) ;
+    XGI_SetMiscRegs( StandTableIndex,  pVBInfo ) ;
+    XGI_SetCRTCRegs( HwDeviceExtension , StandTableIndex,  pVBInfo) ;
+    XGI_SetATTRegs( ModeNo , StandTableIndex , ModeIdIndex, pVBInfo ) ;
+    XGI_SetGRCRegs(  StandTableIndex, pVBInfo ) ;
+    XGI_ClearExt1Regs(pVBInfo) ;
+
+/* if ( pVBInfo->IF_DEF_ExpLink ) */
+    if ( HwDeviceExtension->jChipType == XG27 )
+    {
+      if ( pVBInfo->IF_DEF_LVDS == 0 )
+      {
+        XGI_SetDefaultVCLK( pVBInfo ) ;
+      }
+    }
+
+    temp = ~ProgrammingCRT2 ;
+    pVBInfo->SetFlag &= temp ;
+    pVBInfo->SelectCRT2Rate = 0 ;
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        if ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToLCDA | SetInSlaveMode ) )
+        {
+            pVBInfo->SetFlag |= ProgrammingCRT2 ;
+         }
+    }
+
+    RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ;
+    if ( RefreshRateTableIndex != 0xFFFF )
+    {
+        XGI_SetSync( RefreshRateTableIndex, pVBInfo ) ;
+        XGI_SetCRT1CRTC( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo, HwDeviceExtension ) ;
+        XGI_SetCRT1DE( HwDeviceExtension , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+        XGI_SetCRT1Offset( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+        XGI_SetCRT1VCLK( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
+    }
+
+    if ( ( HwDeviceExtension->jChipType >= XG20 )&&
+         ( HwDeviceExtension->jChipType < XG27 ) ) /* fix H/W DCLK/2 bug */
+    {
+       if ( ( ModeNo == 0x00 ) | (ModeNo == 0x01) )
+       {
+           XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x4E) ;
+           XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE9) ;
+           b3CC =(UCHAR) XGINew_GetReg2(XGINew_P3cc) ;
+           XGINew_SetReg3(XGINew_P3cc ,  (b3CC |= 0x0C) ) ;
+       }
+       else if ( ( ModeNo == 0x04) | ( ModeNo == 0x05) | ( ModeNo == 0x0D) )
+       {
+           XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x1B) ;
+           XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE3) ;
+           b3CC = (UCHAR)XGINew_GetReg2(XGINew_P3cc) ;
+           XGINew_SetReg3(XGINew_P3cc ,  (b3CC |= 0x0C) ) ;
+       }
+    }
+
+    if ( HwDeviceExtension->jChipType >= XG21 )
+    {
+      temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+      if ( temp & 0xA0 )
+      {
+
+        /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ;*/ /* Enable write GPIOF */
+        /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x48 , ~0x20 ) ;*/         /* P. DWN */
+        /* XG21 CRT1 Timing */
+        if ( HwDeviceExtension->jChipType == XG27 )
+          XGI_SetXG27CRTC( ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo );
+        else
+        XGI_SetXG21CRTC( ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo );
+
+        XGI_UpdateXG21CRTC( ModeNo , pVBInfo , RefreshRateTableIndex) ;
+
+        if ( HwDeviceExtension->jChipType == XG27 )
+          XGI_SetXG27LCD( pVBInfo , RefreshRateTableIndex , ModeNo );
+        else
+          XGI_SetXG21LCD( pVBInfo , RefreshRateTableIndex , ModeNo );
+
+        if ( pVBInfo->IF_DEF_LVDS == 1 )
+        {
+          if ( HwDeviceExtension->jChipType == XG27 )
+            XGI_SetXG27LVDSPara(ModeNo,ModeIdIndex, pVBInfo );
+          else
+            XGI_SetXG21LVDSPara(ModeNo,ModeIdIndex, pVBInfo );
+        }
+        /*XGINew_SetRegOR( pVBInfo->P3d4 , 0x48 , 0x20 ) ;*/   /* P. ON */
+      }
+    }
+
+    pVBInfo->SetFlag &= ( ~ProgrammingCRT2 ) ;
+    XGI_SetCRT1FIFO(  ModeNo , HwDeviceExtension,  pVBInfo ) ;
+    XGI_SetCRT1ModeRegs(  HwDeviceExtension , ModeNo , ModeIdIndex , RefreshRateTableIndex , pVBInfo) ;
+
+
+    /* XGI_LoadCharacter(); //dif ifdef TVFont */
+
+    XGI_LoadDAC( ModeNo , ModeIdIndex, pVBInfo ) ;
+    /* XGI_ClearBuffer( HwDeviceExtension , ModeNo, pVBInfo ) ; */
+#ifdef WIN2000
+   if ( pVBInfo->IF_DEF_CH7007 == 1 )  /* [Billy]  2007/05/14  */
+   {
+       VideoDebugPrint((0, "XGI_SetCRT1Group: VBInfo->IF_DEF_CH7007==1\n"));
+       SetCH7007Regs(HwDeviceExtension, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo ) ; /* 07/05/28 */
+   }
+#endif
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetModePtr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGI_GetModePtr( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR index ;
+
+    if ( ModeNo <= 0x13 )
+        index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_StTableIndex ;
+    else
+    {
+        if ( pVBInfo->ModeType <= 0x02 )
+            index = 0x1B ;     /* 02 -> ModeEGA */
+        else
+            index = 0x0F ;
+    }
+    return( index ) ;          /* Get pVBInfo->StandTable index */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetBIOSData */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+/*UCHAR XGI_SetBIOSData( USHORT ModeNo , USHORT ModeIdIndex )
+{
+    return( 0 ) ;
+}
+*/
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_ClearBankRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+/*UCHAR XGI_ClearBankRegs( USHORT ModeNo , USHORT ModeIdIndex )
+{
+    return( 0 ) ;
+}
+*/
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetSeqRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetSeqRegs(  USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR tempah ,
+          SRdata ;
+
+    USHORT i ,
+           modeflag ;
+
+    if ( ModeNo <= 0x13 )
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+    else
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x00 , 0x03 ) ;            /* Set SR0 */
+    tempah=pVBInfo->StandTable[ StandTableIndex ].SR[ 0 ] ;
+
+    i = SetCRT2ToLCDA ;
+    if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+    {
+        tempah |= 0x01 ;
+    }
+    else
+    {
+        if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD ) )
+        {
+            if ( pVBInfo->VBInfo & SetInSlaveMode )
+                tempah |= 0x01 ;
+        }
+    }
+
+    tempah |= 0x20 ;           /* screen off */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , tempah ) ;          /* Set SR1 */
+
+    for( i = 02 ; i <= 04 ; i++ )
+    {
+        SRdata = pVBInfo->StandTable[ StandTableIndex ].SR[ i - 1 ] ;  /* Get SR2,3,4 from file */
+        XGINew_SetReg1( pVBInfo->P3c4 , i , SRdata ) ;                         /* Set SR2 3 4 */
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetMiscRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetMiscRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR Miscdata ;
+
+    Miscdata = pVBInfo->StandTable[ StandTableIndex ].MISC ;   /* Get Misc from file */
+/*
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+        {
+            Miscdata |= 0x0C ;
+        }
+    }
+*/
+
+    XGINew_SetReg3( pVBInfo->P3c2 , Miscdata ) ;               /* Set Misc(3c2) */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRTCRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRTCRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR CRTCdata ;
+    USHORT i ;
+
+    CRTCdata = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+    CRTCdata &= 0x7f ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , CRTCdata ) ;                /* Unlock CRTC */
+
+    for( i = 0 ; i <= 0x18 ; i++ )
+    {
+        CRTCdata = pVBInfo->StandTable[ StandTableIndex ].CRTC[ i ] ;  /* Get CRTC from file */
+        XGINew_SetReg1( pVBInfo->P3d4 , i , CRTCdata ) ;                               /* Set CRTC( 3d4 ) */
+    }
+/*
+    if ( ( HwDeviceExtension->jChipType == XGI_630 )&& ( HwDeviceExtension->jChipRevision == 0x30 ) )
+    {
+        if ( pVBInfo->VBInfo & SetInSlaveMode )
+        {
+            if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV ) )
+            {
+                XGINew_SetReg1( pVBInfo->P3d4 , 0x18 , 0xFE ) ;
+            }
+        }
+    }
+*/
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetATTRegs( USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR ARdata ;
+    USHORT i ,
+           modeflag ;
+
+    if ( ModeNo <= 0x13 )
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+    else
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+
+    for( i = 0 ; i <= 0x13 ; i++ )
+    {
+        ARdata = pVBInfo->StandTable[ StandTableIndex ].ATTR[ i ] ;
+        if ( modeflag & Charx8Dot )    /* ifndef Dot9 */
+        {
+            if ( i == 0x13 )
+            {
+                if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+                    ARdata = 0 ;
+                else
+                {
+                    if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD ) )
+                    {
+                        if ( pVBInfo->VBInfo & SetInSlaveMode )
+                            ARdata = 0 ;
+                    }
+                }
+            }
+        }
+
+        XGINew_GetReg2( pVBInfo->P3da ) ;                      /* reset 3da */
+        XGINew_SetReg3( pVBInfo->P3c0 , i ) ;          /* set index */
+        XGINew_SetReg3( pVBInfo->P3c0 , ARdata ) ;     /* set data */
+    }
+
+    XGINew_GetReg2( pVBInfo->P3da ) ;                  /* reset 3da */
+    XGINew_SetReg3( pVBInfo->P3c0 , 0x14 ) ;           /* set index */
+    XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ;           /* set data */
+    XGINew_GetReg2( pVBInfo->P3da ) ;                  /* Enable Attribute */
+    XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGRCRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGRCRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR GRdata ;
+    USHORT i ;
+
+    for( i = 0 ; i <= 0x08 ; i++ )
+    {
+        GRdata = pVBInfo->StandTable[ StandTableIndex ].GRC[ i ] ;     /* Get GR from file */
+        XGINew_SetReg1( pVBInfo->P3ce , i , GRdata ) ;                 /* Set GR(3ce) */
+    }
+
+    if ( pVBInfo->ModeType > ModeVGA )
+    {
+        GRdata = ( UCHAR )XGINew_GetReg1( pVBInfo->P3ce , 0x05 ) ;
+        GRdata &= 0xBF ;                                               /* 256 color disable */
+        XGINew_SetReg1( pVBInfo->P3ce , 0x05 , GRdata ) ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_ClearExt1Regs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT i ;
+
+    for( i = 0x0A ; i <= 0x0E ; i++ )
+        XGINew_SetReg1( pVBInfo->P3c4 , i , 0x00 ) ;   /* Clear SR0A-SR0E */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetDefaultVCLK */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo )
+{
+
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , 0x20 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ 0 ].SR2B ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ 0 ].SR2C ) ;
+
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , 0x10 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ 1 ].SR2B ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ 1 ].SR2C ) ;
+
+    XGINew_SetRegAND( pVBInfo->P3c4 , 0x31 , ~0x30 ) ;
+    return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetRatePtrCRT2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    SHORT  LCDRefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 } ,
+           LCDARefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 , 0x01 , 0x01 , 0x01 } ;
+
+    USHORT RefreshRateTableIndex , i ,
+         modeflag , index , temp ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+    }
+
+    if ( pVBInfo->IF_DEF_CH7005 == 1 )
+    {
+        if ( pVBInfo->VBInfo & SetCRT2ToTV )
+        {
+            if ( modeflag & HalfDCLK )
+                return( 0 ) ;
+        }
+    }
+
+    if ( ModeNo < 0x14 )
+        return( 0xFFFF ) ;
+
+    index = XGINew_GetReg1( pVBInfo->P3d4 , 0x33 ) ;
+    index = index >> pVBInfo->SelectCRT2Rate ;
+    index &= 0x0F ;
+
+    if ( pVBInfo->LCDInfo & LCDNonExpanding )
+        index = 0 ;
+
+    if ( index > 0 )
+        index-- ;
+
+    if ( pVBInfo->SetFlag & ProgrammingCRT2 )
+    {
+        if ( pVBInfo->IF_DEF_CH7005 == 1 )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToTV )
+            {
+                index = 0 ;
+            }
+        }
+
+        if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+        {
+            if( pVBInfo->IF_DEF_LVDS == 0 )
+            {
+                if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+                    temp = LCDARefreshIndex[ pVBInfo->LCDResInfo & 0x0F ] ;     /* 301b */
+                else
+                    temp = LCDRefreshIndex[ pVBInfo->LCDResInfo & 0x0F ] ;
+
+                if ( index > temp )
+                {
+                    index = temp ;
+                }
+            }
+            else
+            {
+                index = 0 ;
+            }
+        }
+    }
+
+    RefreshRateTableIndex = pVBInfo->EModeIDTable[ ModeIdIndex ].REFindex ;
+    ModeNo = pVBInfo->RefIndex[ RefreshRateTableIndex ].ModeID ;
+    if ( pXGIHWDE->jChipType >= XG20 )  /* for XG20, XG21, XG27 */
+    {
+      /*
+      if ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag & XG2xNotSupport )
+      {
+        index++;
+      }
+      */
+      if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 800 ) &&
+           ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 600 ) )
+      {
+        index++;
+      }
+/* Alan 10/19/2007; do the similiar adjustment like XGISearchCRT1Rate() */
+      if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 1024 ) &&
+           ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 768 ) )
+      {
+        index++;
+      }
+      if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 1280 ) &&
+           ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 1024 ) )
+      {
+        index++;
+      }
+    }
+
+    i = 0 ;
+    do
+    {
+        if ( pVBInfo->RefIndex[ RefreshRateTableIndex + i ].ModeID != ModeNo )
+            break ;
+        temp = pVBInfo->RefIndex[ RefreshRateTableIndex + i ].Ext_InfoFlag ;
+        temp &= ModeInfoFlag ;
+        if ( temp < pVBInfo->ModeType )
+            break ;
+        i++ ;
+        index-- ;
+
+    } while( index != 0xFFFF ) ;
+    if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
+    {
+        if ( pVBInfo->VBInfo & SetInSlaveMode )
+        {
+            temp = pVBInfo->RefIndex[ RefreshRateTableIndex + i - 1 ].Ext_InfoFlag ;
+            if ( temp & InterlaceMode )
+            {
+                i++ ;
+            }
+        }
+    }
+    i-- ;
+    if ( ( pVBInfo->SetFlag & ProgrammingCRT2 ) )
+    {
+        temp = XGI_AjustCRT2Rate( ModeNo , ModeIdIndex , RefreshRateTableIndex , &i, pVBInfo) ;
+    }
+    return( RefreshRateTableIndex + i ) ;                /*return(0x01|(temp1<<1));   */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_AjustCRT2Rate */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_AjustCRT2Rate( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , USHORT *i, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempax ,
+           tempbx ,
+           resinfo ,
+           modeflag ,
+           infoflag ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;  /* si+St_ModeFlag */
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+    }
+
+    resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+    tempbx = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID ;
+    tempax = 0 ;
+
+    if ( pVBInfo->IF_DEF_LVDS == 0 )
+    {
+        if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+        {
+            tempax |= SupportRAMDAC2 ;
+
+            if ( pVBInfo->VBType & VB_XGI301C )
+                tempax |= SupportCRT2in301C ;
+        }
+
+        if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )      /* 301b */
+        {
+            tempax |= SupportLCD ;
+
+            if ( pVBInfo->LCDResInfo != Panel1280x1024 )
+            {
+                if ( pVBInfo->LCDResInfo != Panel1280x960 )
+                {
+                    if ( pVBInfo->LCDInfo & LCDNonExpanding )
+                    {
+                        if ( resinfo >= 9 )
+                        {
+                            tempax = 0 ;
+                            return( 0 ) ;
+                        }
+                    }
+                }
+            }
+        }
+
+        if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )   /* for HiTV */
+        {
+            if ( ( pVBInfo->VBType & VB_XGI301LV ) && ( pVBInfo->VBExtInfo == VB_YPbPr1080i ) )
+            {
+                tempax |= SupportYPbPr ;
+                if ( pVBInfo->VBInfo & SetInSlaveMode )
+                {
+                    if ( resinfo == 4 )
+                        return( 0 ) ;
+
+                    if ( resinfo == 3 )
+                        return( 0 ) ;
+
+                    if ( resinfo > 7 )
+                        return( 0 ) ;
+                }
+            }
+            else
+            {
+                tempax |= SupportHiVisionTV ;
+                if ( pVBInfo->VBInfo & SetInSlaveMode )
+                {
+                    if ( resinfo == 4 )
+                        return( 0 ) ;
+
+                    if ( resinfo == 3 )
+                    {
+                        if ( pVBInfo->SetFlag & TVSimuMode )
+                            return( 0 ) ;
+                    }
+
+                    if ( resinfo > 7 )
+                        return( 0 ) ;
+                }
+            }
+        }
+        else
+        {
+            if ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr | SetCRT2ToHiVisionTV ) )
+            {
+                tempax |= SupportTV ;
+
+                if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+                {
+                    tempax |= SupportTV1024 ;
+                }
+
+                if ( !( pVBInfo->VBInfo & SetPALTV ) )
+                {
+                    if ( modeflag & NoSupportSimuTV )
+                    {
+                        if ( pVBInfo->VBInfo & SetInSlaveMode )
+                        {
+                            if ( !( pVBInfo->VBInfo & SetNotSimuMode ) )
+                            {
+                               return( 0 ) ;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    else               /* for LVDS */
+    {
+        if ( pVBInfo->IF_DEF_CH7005 == 1 )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToTV )
+            {
+                tempax |= SupportCHTV ;
+            }
+        }
+
+        if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+        {
+            tempax |= SupportLCD ;
+
+            if ( resinfo > 0x08 )
+                return( 0 ) ;          /* 1024x768 */
+
+            if ( pVBInfo->LCDResInfo < Panel1024x768 )
+            {
+                if ( resinfo > 0x07 )
+                    return( 0 ) ;      /* 800x600 */
+
+                if ( resinfo == 0x04 )
+                    return( 0 ) ;      /* 512x384 */
+            }
+        }
+    }
+
+    for( ; pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID == tempbx ; ( *i )-- )
+    {
+        infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].Ext_InfoFlag ;
+        if ( infoflag & tempax )
+        {
+            return( 1 ) ;
+        }
+        if ( ( *i ) == 0 )
+            break ;
+    }
+
+    for( ( *i ) = 0 ; ; ( *i )++ )
+    {
+        infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].Ext_InfoFlag ;
+        if ( pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID != tempbx )
+        {
+            return( 0 ) ;
+        }
+
+        if ( infoflag & tempax )
+        {
+            return( 1 ) ;
+        }
+    }
+    return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetSync */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetSync(USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT sync ,
+           temp ;
+
+    sync = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag >> 8 ;      /* di+0x00 */
+    sync &= 0xC0 ;
+    temp = 0x2F ;
+    temp |= sync ;
+    XGINew_SetReg3( pVBInfo->P3c2 , temp ) ;                           /* Set Misc(3c2) */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1CRTC */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1CRTC( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+    UCHAR  index ,
+           data ;
+
+    USHORT i ;
+
+    index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;  /* Get index */
+    index = index&IndexMask ;
+
+    data =( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+    data &= 0x7F ;
+    XGINew_SetReg1(pVBInfo->P3d4,0x11,data);                           /* Unlock CRTC */
+
+    for( i = 0 ; i < 8 ; i++ )
+        pVBInfo->TimingH[ 0 ].data[ i ] = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ i ] ;
+
+    for( i = 0 ; i < 7 ; i++ )
+        pVBInfo->TimingV[ 0 ].data[ i ] = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ i + 8 ] ;
+
+    XGI_SetCRT1Timing_H( pVBInfo, HwDeviceExtension ) ;
+
+
+
+    XGI_SetCRT1Timing_V( ModeIdIndex , ModeNo, pVBInfo ) ;
+
+
+    if( pVBInfo->ModeType > 0x03 )
+        XGINew_SetReg1( pVBInfo->P3d4 , 0x14 , 0x4F ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1Timing_H */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+    UCHAR data , data1, pushax;
+    USHORT i , j ;
+
+    /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */
+    /* XGINew_SetReg1( pVBInfo->P3d4 , 0x56 , 0 ) ; */
+    /* XGINew_SetRegANDOR( pVBInfo->P3d4 ,0x11 , 0x7f , 0x00 ) ; */
+
+    data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;           /* unlock cr0-7 */
+    data &= 0x7F ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , data ) ;
+
+    data = pVBInfo->TimingH[ 0 ].data[ 0 ] ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0 , data ) ;
+
+    for( i = 0x01 ; i <= 0x04 ; i++ )
+    {
+        data = pVBInfo->TimingH[ 0 ].data[ i ] ;
+        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 1 ) , data ) ;
+    }
+
+    for( i = 0x05 ; i <= 0x06 ; i++ )
+    {
+        data = pVBInfo->TimingH[ 0 ].data[ i ];
+        XGINew_SetReg1( pVBInfo->P3c4 ,( USHORT )( i + 6 ) , data ) ;
+    }
+
+    j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0e ) ;
+    j &= 0x1F ;
+    data = pVBInfo->TimingH[ 0 ].data[ 7 ] ;
+    data &= 0xE0 ;
+    data |= j ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x0e , data ) ;
+
+    if ( HwDeviceExtension->jChipType >= XG20 )
+    {
+       data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x04 ) ;
+       data = data - 1 ;
+       XGINew_SetReg1( pVBInfo->P3d4 , 0x04 , data ) ;
+       data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x05 ) ;
+       data1 = data ;
+       data1 &= 0xE0 ;
+       data &= 0x1F ;
+       if ( data == 0 )
+       {
+           pushax = data ;
+           data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0c ) ;
+           data &= 0xFB ;
+           XGINew_SetReg1( pVBInfo->P3c4 , 0x0c , data ) ;
+           data = pushax ;
+       }
+       data = data - 1 ;
+       data |= data1 ;
+       XGINew_SetReg1( pVBInfo->P3d4 , 0x05 , data ) ;
+       data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0e ) ;
+       data = data >> 5 ;
+       data = data + 3 ;
+       if ( data > 7 )
+           data = data - 7 ;
+       data = data << 5 ;
+       XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0e , ~0xE0 , data ) ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1Timing_V */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1Timing_V( USHORT ModeIdIndex , USHORT ModeNo,PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR data ;
+    USHORT i , j ;
+
+    /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */
+    /* XGINew_SetReg1( pVBInfo->P3d4 , 0x56 , 0 ) ; */
+    /* XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , 0x7f , 0x00 ) ; */
+
+    for( i = 0x00 ; i <= 0x01 ; i++ )
+    {
+        data = pVBInfo->TimingV[ 0 ].data[ i ] ;
+        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 6 ) , data ) ;
+    }
+
+    for( i = 0x02 ; i <= 0x03 ; i++ )
+    {
+        data = pVBInfo->TimingV[ 0 ].data[ i ] ;
+        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 0x0e ) , data ) ;
+    }
+
+    for( i = 0x04 ; i <= 0x05 ; i++ )
+    {
+        data = pVBInfo->TimingV[ 0 ].data[ i ] ;
+        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 0x11 ) , data ) ;
+    }
+
+    j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0a ) ;
+    j &= 0xC0 ;
+    data = pVBInfo->TimingV[ 0 ].data[ 6 ] ;
+    data &= 0x3F ;
+    data |= j ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x0a , data ) ;
+
+    data = pVBInfo->TimingV[ 0 ].data[ 6 ] ;
+    data &= 0x80 ;
+    data = data >> 2 ;
+
+    if ( ModeNo <= 0x13 )
+        i = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+    else
+        i = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+
+    i &= DoubleScanMode ;
+    if ( i )
+        data |= 0x80 ;
+
+    j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x09 ) ;
+    j &= 0x5F ;
+    data |= j ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x09 , data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetXG21CRTC */
+/* Input : Stand or enhance CRTC table */
+/* Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F */
+/* Description : Set LCD timing */
+/* --------------------------------------------------------------------- */
+void XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
+{
+  UCHAR StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx ;
+  USHORT Temp1, Temp2, Temp3 ;
+
+  if ( ModeNo <= 0x13 )
+  {
+    StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
+    Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 4 ] ;                /* CR04 HRS */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ;                  /* SR2E [7:0]->HRS */
+    Tempbx = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 5 ] ;                /* Tempbx: CR05 HRE */
+    Tempbx &= 0x1F ;                                                   /* Tempbx: HRE[4:0] */
+    Tempcx = Tempax ;
+    Tempcx &=  0xE0 ;                                                  /* Tempcx: HRS[7:5] */
+    Tempdx = Tempcx | Tempbx ;                                         /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
+    if ( Tempbx < ( Tempax & 0x1F ) )                                  /* IF HRE < HRS */
+      Tempdx |= 0x20 ;                                                 /* Tempdx: HRE = HRE + 0x20 */
+    Tempdx <<= 2 ;                                                     /* Tempdx << 2 */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempdx ) ;                  /* SR2F [7:2]->HRE */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
+
+    Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 16 ] ;       /* Tempax: CR16 VRS */
+    Tempbx = Tempax ;                                                  /* Tempbx=Tempax */
+    Tempax &= 0x01 ;                                                   /* Tempax: VRS[0] */
+    XGINew_SetRegOR( pVBInfo->P3c4 , 0x33 , Tempax ) ;                 /* SR33[0]->VRS */
+    Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ;                /* Tempax: CR7 VRS */
+    Tempdx = Tempbx >> 1 ;                                             /* Tempdx: VRS[7:1] */
+    Tempcx = Tempax & 0x04 ;                                           /* Tempcx: CR7[2] */
+    Tempcx <<= 5 ;                                                     /* Tempcx[7]: VRS[8] */
+    Tempdx |= Tempcx ;                                                 /* Tempdx: VRS[8:1] */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempdx ) ;                  /* SR34[7:0]: VRS[8:1] */
+
+    Temp1 = Tempcx << 1 ;                                              /* Temp1[8]: VRS[8] UCHAR -> USHORT */
+    Temp1 |= Tempbx ;                                                  /* Temp1[8:0]: VRS[8:0] */
+    Tempax &= 0x80 ;                                                   /* Tempax[7]: CR7[7] */
+    Temp2 = Tempax << 2 ;                                              /* Temp2[9]: VRS[9] */
+    Temp1 |= Temp2 ;                                                   /* Temp1[9:0]: VRS[9:0] */
+
+    Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 17 ] ;       /* CR16 VRE */
+    Tempax &= 0x0F ;                                                   /* Tempax[3:0]: VRE[3:0] */
+    Temp2 = Temp1 & 0x3F0 ;                                            /* Temp2[9:4]: VRS[9:4] */
+    Temp2 |= Tempax ;                                                  /* Temp2[9:0]: VRE[9:0] */
+    Temp3 = Temp1 & 0x0F ;                                             /* Temp3[3:0]: VRS[3:0] */
+    if ( Tempax < Temp3 )                                              /* VRE[3:0]<VRS[3:0] */
+      Temp2 |= 0x10 ;                                                  /* Temp2: VRE + 0x10 */
+    Temp2 &= 0xFF ;                                                    /* Temp2[7:0]: VRE[7:0] */
+    Tempax = (UCHAR)Temp2 ;                                            /* Tempax[7:0]: VRE[7:0] */
+    Tempax <<= 2 ;                                                     /* Tempax << 2: VRE[5:0] */
+    Temp1 &= 0x600 ;                                                   /* Temp1[10:9]: VRS[10:9] */
+    Temp1 >>= 9 ;                                                      /* [10:9]->[1:0] */
+    Tempbx = (UCHAR)Temp1 ;                                            /* Tempbx[1:0]: VRS[10:9] */
+    Tempax |= Tempbx ;                                                 /* VRE[5:0]VRS[10:9] */
+    Tempax &= 0x7F ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , Tempax ) ;                  /* SR3F D[7:2]->VRE D[1:0]->VRS */
+  }
+  else
+  {
+    index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ;            /* Tempax: CR4 HRS */
+    Tempcx = Tempax ;                                                  /* Tempcx: HRS */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ;                          /* SR2E[7:0]->HRS */
+
+    Tempdx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ;            /* SRB */
+    Tempdx &= 0xC0 ;                                                   /* Tempdx[7:6]: SRB[7:6] */
+    Temp1 = Tempdx ;                                                   /* Temp1[7:6]: HRS[9:8] */
+    Temp1 <<= 2 ;                                                      /* Temp1[9:8]: HRS[9:8] */
+    Temp1 |= Tempax ;                                                  /* Temp1[9:0]: HRS[9:0] */
+
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 4 ] ;            /* CR5 HRE */
+    Tempax &= 0x1F ;                                                   /* Tempax[4:0]: HRE[4:0] */
+
+    Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 6 ] ;            /* SRC */
+    Tempbx &= 0x04 ;                                                   /* Tempbx[2]: HRE[5] */
+    Tempbx <<= 3 ;                                                     /* Tempbx[5]: HRE[5] */
+    Tempax |= Tempbx ;                                                 /* Tempax[5:0]: HRE[5:0] */
+
+    Temp2 = Temp1 & 0x3C0 ;                                            /* Temp2[9:6]: HRS[9:6] */
+    Temp2 |= Tempax ;                                                  /* Temp2[9:0]: HRE[9:0] */
+
+    Tempcx &= 0x3F ;                                                   /* Tempcx[5:0]: HRS[5:0] */
+    if( Tempax < Tempcx )                                              /* HRE < HRS */
+      Temp2 |= 0x40 ;                                                   /* Temp2 + 0x40 */
+
+    Temp2 &= 0xFF ;
+    Tempax = (UCHAR)Temp2 ;                                            /* Tempax: HRE[7:0] */
+    Tempax <<= 2 ;                                                     /* Tempax[7:2]: HRE[5:0] */
+    Tempdx >>= 6 ;                                                     /* Tempdx[7:6]->[1:0] HRS[9:8] */
+    Tempax |= Tempdx ;                                                 /* HRE[5:0]HRS[9:8] */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempax ) ;                  /* SR2F D[7:2]->HRE, D[1:0]->HRS */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
+
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 10 ] ;           /* CR10 VRS */
+    Tempbx = Tempax ;                                                  /* Tempbx: VRS */
+    Tempax &= 0x01 ;                                                   /* Tempax[0]: VRS[0] */
+    XGINew_SetRegOR( pVBInfo->P3c4 , 0x33 , Tempax ) ;                 /* SR33[0]->VRS[0] */
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 9 ] ;            /* CR7[2][7] VRE */
+    Tempcx = Tempbx >> 1 ;                                             /* Tempcx[6:0]: VRS[7:1] */
+    Tempdx = Tempax & 0x04 ;                                           /* Tempdx[2]: CR7[2] */
+    Tempdx <<= 5 ;                                                     /* Tempdx[7]: VRS[8] */
+    Tempcx |= Tempdx ;                                                 /* Tempcx[7:0]: VRS[8:1] */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempcx ) ;                  /* SR34[8:1]->VRS */
+
+    Temp1 = Tempdx ;                                                   /* Temp1[7]: Tempdx[7] */
+    Temp1 <<= 1 ;                                                      /* Temp1[8]: VRS[8] */
+    Temp1 |= Tempbx ;                                                  /* Temp1[8:0]: VRS[8:0] */
+    Tempax &= 0x80 ;
+    Temp2 = Tempax << 2 ;                                              /* Temp2[9]: VRS[9] */
+    Temp1 |= Temp2 ;                                                   /* Temp1[9:0]: VRS[9:0] */
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ;           /* Tempax: SRA */
+    Tempax &= 0x08 ;                                                   /* Tempax[3]: VRS[3] */
+    Temp2 = Tempax ;
+    Temp2 <<= 7 ;                                                      /* Temp2[10]: VRS[10] */
+    Temp1 |= Temp2 ;                                                   /* Temp1[10:0]: VRS[10:0] */
+
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 11 ] ;           /* Tempax: CR11 VRE */
+    Tempax &= 0x0F ;                                                   /* Tempax[3:0]: VRE[3:0] */
+    Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ;           /* Tempbx: SRA */
+    Tempbx &= 0x20 ;                                                   /* Tempbx[5]: VRE[5] */
+    Tempbx >>= 1 ;                                                     /* Tempbx[4]: VRE[4] */
+    Tempax |= Tempbx ;                                                 /* Tempax[4:0]: VRE[4:0] */
+    Temp2 = Temp1 & 0x7E0 ;                                            /* Temp2[10:5]: VRS[10:5] */
+    Temp2 |= Tempax ;                                                  /* Temp2[10:5]: VRE[10:5] */
+
+    Temp3 = Temp1 & 0x1F ;                                             /* Temp3[4:0]: VRS[4:0] */
+    if ( Tempax < Temp3 )                                              /* VRE < VRS */
+      Temp2 |= 0x20 ;                                                  /* VRE + 0x20 */
+
+    Temp2 &= 0xFF ;
+    Tempax = (UCHAR)Temp2 ;                                            /* Tempax: VRE[7:0] */
+    Tempax <<= 2 ;                                                     /* Tempax[7:0]; VRE[5:0]00 */
+    Temp1 &= 0x600 ;                                                   /* Temp1[10:9]: VRS[10:9] */
+    Temp1 >>= 9 ;                                                      /* Temp1[1:0]: VRS[10:9] */
+    Tempbx = (UCHAR)Temp1 ;
+    Tempax |= Tempbx ;                                                 /* Tempax[7:0]: VRE[5:0]VRS[10:9] */
+    Tempax &= 0x7F ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , Tempax ) ;                  /* SR3F D[7:2]->VRE D[1:0]->VRS */
+  }
+}
+
+void XGI_SetXG27CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
+{
+  USHORT StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx ;
+
+  if ( ModeNo <= 0x13 )
+  {
+    StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
+    Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 4 ] ;                /* CR04 HRS */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ;                  /* SR2E [7:0]->HRS */
+    Tempbx = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 5 ] ;                /* Tempbx: CR05 HRE */
+    Tempbx &= 0x1F ;                                                   /* Tempbx: HRE[4:0] */
+    Tempcx = Tempax ;
+    Tempcx &=  0xE0 ;                                                  /* Tempcx: HRS[7:5] */
+    Tempdx = Tempcx | Tempbx ;                                         /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
+    if ( Tempbx < ( Tempax & 0x1F ) )                                  /* IF HRE < HRS */
+      Tempdx |= 0x20 ;                                                 /* Tempdx: HRE = HRE + 0x20 */
+    Tempdx <<= 2 ;                                                     /* Tempdx << 2 */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempdx ) ;                  /* SR2F [7:2]->HRE */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
+
+    Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 16 ] ;       /* Tempax: CR10 VRS */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempax ) ;                  /* SR34[7:0]->VRS */
+    Tempcx = Tempax ;                                                  /* Tempcx=Tempax=VRS[7:0] */
+    Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ;                /* Tempax[7][2]: CR7[7][2] VRS[9][8] */
+    Tempbx = Tempax ;                                                  /* Tempbx=CR07 */
+    Tempax &= 0x04 ;                                                   /* Tempax[2]: CR07[2] VRS[8] */
+    Tempax >>= 2;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x01, Tempax ) ;        /* SR35 D[0]->VRS D[8] */
+    Tempcx |= (Tempax << 8) ;                                          /* Tempcx[8] |= VRS[8] */
+    Tempcx |= (Tempbx & 0x80)<<2;                                      /* Tempcx[9] |= VRS[9] */
+
+
+    Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 17 ] ;       /* CR11 VRE */
+    Tempax &= 0x0F ;                                                   /* Tempax: VRE[3:0] */
+    Tempbx = Tempcx ;                                                  /* Tempbx=Tempcx=VRS[9:0] */
+    Tempbx &= 0x3F0 ;                                                  /* Tempbx[9:4]: VRS[9:4] */
+    Tempbx |= Tempax ;                                                 /* Tempbx[9:0]: VRE[9:0] */
+    if ( Tempax <= (Tempcx & 0x0F) )                                   /* VRE[3:0]<=VRS[3:0] */
+      Tempbx |= 0x10 ;                                                 /* Tempbx: VRE + 0x10 */
+    Tempax = (UCHAR)Tempbx & 0xFF;                                     /* Tempax[7:0]: VRE[7:0] */
+    Tempax <<= 2 ;                                                     /* Tempax << 2: VRE[5:0] */
+    Tempcx = (Tempcx&0x600)>>8;                                         /* Tempcx VRS[10:9] */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC, Tempax ) ;        /* SR3F D[7:2]->VRE D[5:0] */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x06, Tempcx ) ;       /* SR35 D[2:1]->VRS[10:9] */
+  }
+  else
+  {
+    index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ;            /* Tempax: CR4 HRS */
+    Tempbx = Tempax ;                                                  /* Tempbx: HRS[7:0] */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ;                          /* SR2E[7:0]->HRS */
+
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ;            /* SR0B */
+    Tempax &= 0xC0 ;                                                   /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
+    Tempbx |= (Tempax << 2);                                   /* Tempbx: HRS[9:0] */
+
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 4 ] ;            /* CR5 HRE */
+    Tempax &= 0x1F ;                                                   /* Tempax[4:0]: HRE[4:0] */
+    Tempcx = Tempax ;                                                  /* Tempcx: HRE[4:0] */
+
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 6 ] ;            /* SRC */
+    Tempax &= 0x04 ;                                                   /* Tempax[2]: HRE[5] */
+    Tempax <<= 3 ;                                                         /* Tempax[5]: HRE[5] */
+    Tempcx |= Tempax ;                                                 /* Tempcx[5:0]: HRE[5:0] */
+
+    Tempbx = Tempbx & 0x3C0 ;                                  /* Tempbx[9:6]: HRS[9:6] */
+    Tempbx |= Tempcx ;                                                 /* Tempbx: HRS[9:6]HRE[5:0] */
+
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ;            /* Tempax: CR4 HRS */
+    Tempax &= 0x3F ;                                                   /* Tempax: HRS[5:0] */
+    if( Tempcx <= Tempax )                                             /* HRE[5:0] < HRS[5:0] */
+      Tempbx += 0x40 ;                          /* Tempbx= Tempbx + 0x40 : HRE[9:0]*/
+
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ;            /* SR0B */
+    Tempax &= 0xC0 ;                                                   /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
+    Tempax >>= 6;                               /* Tempax[1:0]: HRS[9:8]*/
+    Tempax |= ((Tempbx << 2) & 0xFF);           /* Tempax[7:2]: HRE[5:0] */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempax ) ;                  /* SR2F [7:2][1:0]: HRE[5:0]HRS[9:8] */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
+
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 10 ] ;           /* CR10 VRS */
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempax ) ;                  /* SR34[7:0]->VRS[7:0] */
+
+    Tempcx = Tempax ;                                                  /* Tempcx <= VRS[7:0] */
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 9 ] ;            /* CR7[7][2] VRS[9][8] */
+    Tempbx = Tempax ;                                                  /* Tempbx <= CR07[7:0] */
+    Tempax = Tempax & 0x04 ;                                   /* Tempax[2]: CR7[2]: VRS[8] */
+    Tempax >>= 2 ;                                                         /* Tempax[0]: VRS[8] */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x01 , Tempax ) ;      /* SR35[0]: VRS[8] */
+    Tempcx |= (Tempax<<8) ;                                            /* Tempcx <= VRS[8:0] */
+    Tempcx |= ((Tempbx&0x80)<<2) ;                             /* Tempcx <= VRS[9:0] */
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ;           /* Tempax: SR0A */
+    Tempax &= 0x08;                             /* SR0A[3] VRS[10] */
+    Tempcx |= (Tempax<<7) ;                                    /* Tempcx <= VRS[10:0] */
+
+
+    Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 11 ] ;           /* Tempax: CR11 VRE */
+    Tempax &= 0x0F ;                                                   /* Tempax[3:0]: VRE[3:0] */
+    Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ;           /* Tempbx: SR0A */
+    Tempbx &= 0x20 ;                                                   /* Tempbx[5]: SR0A[5]: VRE[4] */
+    Tempbx >>= 1 ;                                                         /* Tempbx[4]: VRE[4] */
+    Tempax |= Tempbx ;                                                 /* Tempax[4:0]: VRE[4:0] */
+    Tempbx = Tempcx ;                                                  /* Tempbx: VRS[10:0] */
+    Tempbx &= 0x7E0 ;                                              /* Tempbx[10:5]: VRS[10:5] */
+    Tempbx |= Tempax ;                                                 /* Tempbx: VRS[10:5]VRE[4:0] */
+
+    if ( Tempbx <= Tempcx )                                            /* VRE <= VRS */
+      Tempbx |= 0x20 ;                                                 /* VRE + 0x20 */
+
+    Tempax = (Tempbx<<2) & 0xFF ;                                      /* Tempax: Tempax[7:0]; VRE[5:0]00 */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , Tempax ) ;      /* SR3F[7:2]:VRE[5:0] */
+    Tempax = Tempcx >> 8;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x07 , Tempax ) ;      /* SR35[2:0]:VRS[10:8] */
+  }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetXG21LCD */
+/* Input : */
+/* Output : FCLK duty cycle, FCLK delay compensation */
+/* Description : All values set zero */
+/* --------------------------------------------------------------------- */
+void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo)
+{
+  USHORT Data , Temp , b3CC ;
+  USHORT XGI_P3cc ;
+
+  XGI_P3cc = pVBInfo->P3cc ;
+
+  XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , 0x00 ) ;
+  XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , 0x00 ) ;
+  XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x00 ) ;
+  XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x00 ) ;
+  if ( ((*pVBInfo->pDVOSetting)&0xC0) == 0xC0 )
+  {
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , *pVBInfo->pCR2E ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , *pVBInfo->pCR2F ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , *pVBInfo->pCR46 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , *pVBInfo->pCR47 ) ;
+  }
+
+  Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
+
+  if ( Temp & 0x01 )
+  {
+    XGINew_SetRegOR( pVBInfo->P3c4 , 0x06 , 0x40 ) ; /* 18 bits FP */
+    XGINew_SetRegOR( pVBInfo->P3c4 , 0x09 , 0x40 ) ;
+  }
+
+  XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x01 ) ;   /* Negative blank polarity */
+
+  XGINew_SetRegAND( pVBInfo->P3c4 , 0x30 , ~0x20 ) ;
+  XGINew_SetRegAND( pVBInfo->P3c4 , 0x35 , ~0x80 ) ;
+
+  if ( ModeNo <= 0x13 )
+  {
+    b3CC = (UCHAR) XGINew_GetReg2( XGI_P3cc ) ;
+    if ( b3CC & 0x40 )
+      XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
+    if ( b3CC & 0x80 )
+      XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
+  }
+  else
+  {
+    Data = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+    if ( Data & 0x4000 )
+      XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
+    if ( Data & 0x8000 )
+      XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
+  }
+}
+
+void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo)
+{
+  USHORT Data , Temp , b3CC ;
+  USHORT XGI_P3cc ;
+
+  XGI_P3cc = pVBInfo->P3cc ;
+
+  XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , 0x00 ) ;
+  XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , 0x00 ) ;
+  XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x00 ) ;
+  XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x00 ) ;
+
+  Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
+  if ( ( Temp & 0x03 ) == 0 )  /* dual 12 */
+  {
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x13 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x13 ) ;
+  }
+
+  if ( ((*pVBInfo->pDVOSetting)&0xC0) == 0xC0 )
+  {
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , *pVBInfo->pCR2E ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , *pVBInfo->pCR2F ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , *pVBInfo->pCR46 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , *pVBInfo->pCR47 ) ;
+  }
+
+  XGI_SetXG27FPBits(pVBInfo);
+
+  XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x01 ) ;   /* Negative blank polarity */
+
+  XGINew_SetRegAND( pVBInfo->P3c4 , 0x30 , ~0x20 ) ; /* Hsync polarity */
+  XGINew_SetRegAND( pVBInfo->P3c4 , 0x35 , ~0x80 ) ; /* Vsync polarity */
+
+  if ( ModeNo <= 0x13 )
+  {
+    b3CC = (UCHAR) XGINew_GetReg2( XGI_P3cc ) ;
+    if ( b3CC & 0x40 )
+      XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
+    if ( b3CC & 0x80 )
+      XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
+  }
+  else
+  {
+    Data = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+    if ( Data & 0x4000 )
+      XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
+    if ( Data & 0x8000 )
+      XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
+  }
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_UpdateXG21CRTC */
+/* Input : */
+/* Output : CRT1 CRTC */
+/* Description : Modify CRT1 Hsync/Vsync to fix LCD mode timing */
+/* --------------------------------------------------------------------- */
+void XGI_UpdateXG21CRTC( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo , USHORT RefreshRateTableIndex )
+{
+  int i , index = -1;
+
+  XGINew_SetRegAND( pVBInfo->P3d4 , 0x11 , 0x7F ) ;            /* Unlock CR0~7 */
+  if ( ModeNo <= 0x13 )
+  {
+    for( i = 0 ; i < 12 ; i++ )
+    {
+      if ( ModeNo == pVBInfo->UpdateCRT1[ i ].ModeID )
+        index = i ;
+    }
+  }
+  else
+  {
+    if ( ModeNo == 0x2E && ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ==  RES640x480x60 ) )
+      index = 12 ;
+    else if ( ModeNo == 0x2E && ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC == RES640x480x72 ) )
+      index = 13 ;
+    else if ( ModeNo == 0x2F )
+      index = 14 ;
+    else if ( ModeNo == 0x50 )
+      index = 15 ;
+    else if ( ModeNo == 0x59 )
+      index = 16 ;
+  }
+
+  if( index != -1 )
+  {
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x02 , pVBInfo->UpdateCRT1[ index ].CR02 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x03 , pVBInfo->UpdateCRT1[ index ].CR03 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , pVBInfo->UpdateCRT1[ index ].CR15 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , pVBInfo->UpdateCRT1[ index ].CR16 ) ;
+  }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1DE */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1DE( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo,USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT resindex ,
+           tempax ,
+           tempbx ,
+           tempcx ,
+           temp ,
+           modeflag ;
+
+    UCHAR data ;
+
+    resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+        tempax = pVBInfo->StResInfo[ resindex ].HTotal ;
+        tempbx = pVBInfo->StResInfo[ resindex ].VTotal ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+        tempax = pVBInfo->ModeResInfo[ resindex ].HTotal ;
+        tempbx = pVBInfo->ModeResInfo[ resindex ].VTotal ;
+    }
+
+    if ( modeflag & HalfDCLK )
+        tempax = tempax >> 1 ;
+
+    if ( ModeNo > 0x13 )
+    {
+        if ( modeflag & HalfDCLK )
+            tempax = tempax << 1 ;
+
+        temp = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+
+        if ( temp & InterlaceMode )
+            tempbx = tempbx >> 1 ;
+
+        if ( modeflag & DoubleScanMode )
+            tempbx = tempbx << 1 ;
+    }
+
+    tempcx = 8 ;
+
+    /* if ( !( modeflag & Charx8Dot ) ) */
+    /* tempcx = 9 ; */
+
+    tempax /= tempcx ;
+    tempax -= 1 ;
+    tempbx -= 1 ;
+    tempcx = tempax ;
+    temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+    data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+    data &= 0x7F ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , data ) ;            /* Unlock CRTC */
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x01 , ( USHORT )( tempcx & 0xff ) ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x0b , ~0x0c , ( USHORT )( ( tempcx & 0x0ff00 ) >> 10 ) ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x12 , ( USHORT )( tempbx & 0xff ) ) ;
+    tempax = 0 ;
+    tempbx = tempbx >> 8 ;
+
+    if ( tempbx & 0x01 )
+        tempax |= 0x02 ;
+
+    if ( tempbx & 0x02 )
+        tempax |= 0x40 ;
+
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x42 , tempax ) ;
+    data =( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x07 ) ;
+    data &= 0xFF ;
+    tempax = 0 ;
+
+    if ( tempbx & 0x04 )
+        tempax |= 0x02 ;
+
+    XGINew_SetRegANDOR( pVBInfo->P3d4 ,0x0a , ~0x02 , tempax ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetResInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT         XGI_GetResInfo(USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT resindex ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        resindex = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;   /* si+St_ResInfo */
+    }
+    else
+    {
+        resindex = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;  /* si+Ext_ResInfo */
+    }
+    return( resindex ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1Offset */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1Offset(  USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT temp ,
+           ah ,
+           al ,
+           temp2 ,
+           i ,
+           DisplayUnit ;
+
+    /* GetOffset */
+    temp = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeInfo ;
+    temp = temp >> 8 ;
+    temp = pVBInfo->ScreenOffset[ temp ] ;
+
+    temp2 = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+    temp2 &= InterlaceMode ;
+
+    if ( temp2 )
+        temp = temp << 1;
+
+    temp2 = pVBInfo->ModeType - ModeEGA ;
+
+    switch( temp2 )
+    {
+        case 0:
+            temp2 = 1 ;
+            break ;
+        case 1:
+            temp2 = 2 ;
+            break ;
+        case 2:
+            temp2 = 4 ;
+            break ;
+        case 3:
+            temp2 = 4 ;
+            break ;
+        case 4:
+            temp2 = 6 ;
+            break;
+        case 5:
+            temp2 = 8 ;
+            break ;
+        default:
+            break ;
+    }
+
+    if ( ( ModeNo >= 0x26 ) && ( ModeNo <= 0x28 ) )
+        temp = temp * temp2 + temp2 / 2 ;
+    else
+        temp *= temp2 ;
+
+    /* SetOffset */
+    DisplayUnit = temp ;
+    temp2 = temp ;
+    temp = temp >> 8 ;         /* ah */
+    temp &= 0x0F ;
+    i = XGINew_GetReg1( pVBInfo->P3c4 , 0x0E ) ;
+    i &= 0xF0 ;
+    i |= temp ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x0E , i ) ;
+
+    temp =( UCHAR )temp2 ;
+    temp &= 0xFF ;             /* al */
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x13 , temp ) ;
+
+    /* SetDisplayUnit */
+    temp2 = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+    temp2 &= InterlaceMode ;
+    if ( temp2 )
+        DisplayUnit >>= 1 ;
+
+    DisplayUnit = DisplayUnit << 5 ;
+    ah = ( DisplayUnit & 0xff00 ) >> 8 ;
+    al = DisplayUnit & 0x00ff ;
+    if ( al == 0 )
+        ah += 1 ;
+    else
+        ah += 2 ;
+
+    if ( HwDeviceExtension->jChipType >= XG20 )
+        if ( ( ModeNo == 0x4A ) | (ModeNo == 0x49 ) )
+            ah -= 1 ;
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x10 , ah ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1VCLK */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1VCLK( USHORT ModeNo , USHORT ModeIdIndex ,
+                        PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR index , data ;
+    USHORT vclkindex ;
+
+    if ( pVBInfo->IF_DEF_LVDS == 1 )
+    {
+        index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
+        data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ index ].SR2B ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ index ].SR2C ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ;
+    }
+    else if ( ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) && ( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
+    {
+        vclkindex = XGI_GetVCLK2Ptr( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+        data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ;
+        data = pVBInfo->VBVCLKData[ vclkindex ].Part4_A ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , data ) ;
+        data = pVBInfo->VBVCLKData[ vclkindex ].Part4_B ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , data ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ;
+    }
+    else
+    {
+        index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
+        data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ index ].SR2B ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ index ].SR2C ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ;
+    }
+
+    if ( HwDeviceExtension->jChipType >= XG20 )
+    {
+       if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag & HalfDCLK )
+       {
+       data = XGINew_GetReg1( pVBInfo->P3c4 , 0x2B ) ;
+       XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , data ) ;
+       data = XGINew_GetReg1( pVBInfo->P3c4 , 0x2C ) ;
+       index = data ;
+       index &= 0xE0 ;
+       data &= 0x1F ;
+       data = data << 1 ;
+       data += 1 ;
+       data |= index ;
+       XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , data ) ;
+       }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1FIFO */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1FIFO( USHORT ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT data ;
+
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3D ) ;
+    data &= 0xfe ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x3D , data ) ;    /* diable auto-threshold */
+
+    if ( ModeNo > 0x13 )
+    {
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0x34 ) ;
+        data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ;
+        data &= 0xC0 ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data | 0x30) ;
+        data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3D ) ;
+        data |= 0x01 ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x3D , data ) ;
+    }
+    else
+    {
+        if (HwDeviceExtension->jChipType == XG27)
+        {
+          XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0x0E ) ;
+          data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ;
+          data &= 0xC0 ;
+          XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data | 0x20 ) ;
+        }
+        else
+        {
+          XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0xAE ) ;
+          data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ;
+          data &= 0xF0 ;
+          XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data ) ;
+        }
+    }
+
+    if (HwDeviceExtension->jChipType == XG21)
+    {
+        XGI_SetXG21FPBits(pVBInfo);                 /* Fix SR9[7:6] can't read back */
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1ModeRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1ModeRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension ,
+                            USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT data ,
+           data2 ,
+           data3 ,
+           infoflag = 0 ,
+           modeflag ,
+           resindex ,
+           xres ;
+
+    if ( ModeNo > 0x13 )
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+        infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+    }
+    else
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;    /* si+St_ModeFlag */
+
+    if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) & 0x01 )
+      XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , 0x3F , 0x00 ) ;
+
+    if ( ModeNo > 0x13 )
+        data = infoflag ;
+    else
+        data = 0 ;
+
+    data2 = 0 ;
+
+    if ( ModeNo > 0x13 )
+    {
+        if ( pVBInfo->ModeType > 0x02 )
+        {
+            data2 |= 0x02 ;
+            data3 = pVBInfo->ModeType - ModeVGA ;
+            data3 = data3 << 2 ;
+            data2 |= data3 ;
+        }
+    }
+
+    data &= InterlaceMode ;
+
+    if ( data )
+        data2 |= 0x20 ;
+
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0x3F , data2 ) ;
+    /* XGINew_SetReg1(pVBInfo->P3c4,0x06,data2); */
+    resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+    if ( ModeNo <= 0x13 )
+        xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+    else
+        xres = pVBInfo->ModeResInfo[ resindex ].HTotal ;                         /* xres->ax */
+
+    data = 0x0000 ;
+    if ( infoflag & InterlaceMode )
+    {
+        if ( xres == 1024 )
+            data = 0x0035 ;
+        else if ( xres == 1280 )
+            data = 0x0048 ;
+    }
+
+    data2 = data & 0x00FF ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x19 , 0xFF , data2 ) ;
+    data2 = ( data & 0xFF00 ) >> 8 ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x19 , 0xFC , data2 ) ;
+
+    if( modeflag & HalfDCLK )
+        XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xF7 , 0x08 ) ;
+
+    data2 = 0 ;
+
+    if ( modeflag & LineCompareOff )
+        data2 |= 0x08 ;
+
+    if ( ModeNo > 0x13 )
+    {
+        if ( pVBInfo->ModeType == ModeEGA )
+            data2 |= 0x40 ;
+    }
+
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0F , ~0x48 , data2 ) ;
+    data = 0x60 ;
+    if ( pVBInfo->ModeType != ModeText )
+    {
+        data = data ^ 0x60 ;
+        if ( pVBInfo->ModeType != ModeEGA )
+        {
+            data = data ^ 0xA0 ;
+        }
+    }
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x21 , 0x1F , data ) ;
+
+    XGI_SetVCLKState( HwDeviceExtension , ModeNo , RefreshRateTableIndex, pVBInfo) ;
+
+    /* if(modeflag&HalfDCLK)//030305 fix lowresolution bug */
+    /* if(XGINew_IF_DEF_NEW_LOWRES) */
+    /* XGI_VesaLowResolution(ModeNo,ModeIdIndex);//030305 fix lowresolution bug */
+
+    data=XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ;
+
+    if (HwDeviceExtension->jChipType == XG27 )
+    {
+       if ( data & 0x40 )
+           data = 0x2c ;
+       else
+           data = 0x6c ;
+       XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ;
+       XGINew_SetRegOR( pVBInfo->P3d4 , 0x51 , 0x10 ) ;
+    }
+    else
+    if (HwDeviceExtension->jChipType >= XG20 )
+    {
+       if ( data & 0x40 )
+           data = 0x33 ;
+       else
+           data = 0x73 ;
+       XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ;
+       XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0x02 ) ;
+    }
+    else
+    {
+    if ( data & 0x40 )
+        data = 0x2c ;
+    else
+        data = 0x6c ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ;
+    }
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetVCLKState */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetVCLKState(  PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT data ,
+           data2 = 0 ;
+    SHORT  VCLK ;
+
+    UCHAR  index ;
+
+    if ( ModeNo <= 0x13 )
+        VCLK = 0 ;
+    else
+    {
+        index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
+        index &= IndexMask ;
+        VCLK = pVBInfo->VCLKData[ index ].CLOCK ;
+    }
+
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) ;
+    data &= 0xf3 ;
+    if ( VCLK >= 200 )
+        data |= 0x0c ; /* VCLK > 200 */
+
+    if ( HwDeviceExtension->jChipType >= XG20 )
+        data &= ~0x04 ; /* 2 pixel mode */
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , data ) ;
+
+    if ( HwDeviceExtension->jChipType < XG20 )
+    {
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ;
+    data &= 0xE7 ;
+    if ( VCLK < 200 )
+        data |= 0x10 ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , data ) ;
+    }
+
+/*  Jong for Adavantech LCD ripple issue
+    if ( ( VCLK >= 0 ) && ( VCLK < 135 ) )
+        data2 = 0x03 ;
+    else if ( ( VCLK >= 135 ) && ( VCLK < 160 ) )
+        data2 = 0x02 ;
+    else if ( ( VCLK >= 160 ) && ( VCLK < 260 ) )
+        data2 = 0x01 ;
+    else if ( VCLK > 260 )
+          data2 = 0x00 ;
+*/
+    data2 = 0x00 ;
+
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x07 , 0xFC , data2 ) ;
+    if (HwDeviceExtension->jChipType >= XG27 )
+    {
+      XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x40 , 0xFC , data2&0x03 ) ;
+    }
+
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_VesaLowResolution */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+/*void XGI_VesaLowResolution( USHORT ModeNo , USHORT ModeIdIndex ,PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT modeflag;
+
+    if ( ModeNo > 0x13 )
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+    else
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+
+    if ( ModeNo > 0x13 )
+    {
+        if ( modeflag & DoubleScanMode )
+        {
+            if ( modeflag & HalfDCLK )
+            {
+                if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+                {
+                    if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
+                    {
+                        if ( pVBInfo->VBInfo & SetInSlaveMode )
+                        {
+                            XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xf7 , 0x00 ) ;
+                            XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0x7f , 0x00 ) ;
+                            return ;
+                        }
+                    }
+                }
+                XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0xff , 0x80 ) ;
+                XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xf7 , 0x00 ) ;
+                return ;
+            }
+        }
+    }
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0x7f , 0x00 ) ;
+}
+*/
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_LoadDAC */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_LoadDAC( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT data , data2 , time ,
+           i  , j , k , m , n , o ,
+           si , di , bx , dl , al , ah , dh ,
+           *table = NULL ;
+
+    if ( ModeNo <= 0x13 )
+        data = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+    else
+        data = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+
+    data &= DACInfoFlag ;
+    time = 64 ;
+
+    if ( data == 0x00 )
+        table = XGINew_MDA_DAC ;
+    else if ( data == 0x08 )
+        table = XGINew_CGA_DAC ;
+    else if ( data == 0x10 )
+        table = XGINew_EGA_DAC ;
+    else if ( data == 0x18 )
+    {
+        time = 256 ;
+        table = XGINew_VGA_DAC ;
+    }
+
+    if ( time == 256 )
+        j = 16 ;
+    else
+        j = time ;
+
+    XGINew_SetReg3( pVBInfo->P3c6 , 0xFF ) ;
+    XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ;
+
+    for( i = 0 ; i < j ; i++ )
+    {
+        data = table[ i ] ;
+
+        for( k = 0 ; k < 3 ; k++ )
+        {
+            data2 = 0 ;
+
+            if ( data & 0x01 )
+                data2 = 0x2A ;
+
+            if ( data & 0x02 )
+                data2 += 0x15 ;
+
+            XGINew_SetReg3( pVBInfo->P3c9 , data2 ) ;
+            data = data >> 2 ;
+        }
+    }
+
+    if ( time == 256 )
+    {
+        for( i = 16 ; i < 32 ; i++ )
+        {
+            data = table[ i ] ;
+
+            for( k = 0 ; k < 3 ; k++ )
+                XGINew_SetReg3( pVBInfo->P3c9 , data ) ;
+        }
+
+        si = 32 ;
+
+        for( m = 0 ; m < 9 ; m++ )
+        {
+            di = si ;
+            bx = si + 0x04 ;
+            dl = 0 ;
+
+            for( n = 0 ; n < 3 ; n++ )
+            {
+                for( o = 0 ; o < 5 ; o++ )
+                {
+                    dh = table[ si ] ;
+                    ah = table[ di ] ;
+                    al = table[ bx ] ;
+                    si++ ;
+                    XGI_WriteDAC( dl , ah , al , dh, pVBInfo ) ;
+                }
+
+                si -= 2 ;
+
+                for( o = 0 ; o < 3 ; o++ )
+                {
+                    dh = table[ bx ] ;
+                    ah = table[ di ] ;
+                    al = table[ si ] ;
+                    si-- ;
+                    XGI_WriteDAC( dl , ah , al , dh, pVBInfo ) ;
+                }
+
+                dl++ ;
+            }
+
+            si += 5 ;
+        }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_WriteDAC */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_WriteDAC( USHORT dl , USHORT ah , USHORT al , USHORT dh,PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT temp , bh , bl ;
+
+    bh = ah ;
+    bl = al ;
+
+    if ( dl != 0 )
+    {
+        temp = bh ;
+        bh = dh ;
+        dh = temp ;
+        if ( dl == 1 )
+        {
+            temp = bl ;
+            bl = dh ;
+            dh = temp ;
+        }
+        else
+        {
+            temp = bl ;
+            bl = bh ;
+            bh = temp ;
+        }
+    }
+    XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )dh ) ;
+    XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )bh ) ;
+    XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )bl ) ;
+}
+
+#if 0
+/* --------------------------------------------------------------------- */
+/* Function : XGI_ClearBuffer */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_ClearBuffer( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo, PVB_DEVICE_INFO  pVBInfo)
+{
+    PVOID VideoMemoryAddress = ( PVOID )HwDeviceExtension->pjVideoMemoryAddress ;
+    ULONG AdapterMemorySize  = ( ULONG )HwDeviceExtension->ulVideoMemorySize ;
+    PUSHORT pBuffer ;
+#ifndef LINUX_XF86
+    int i ;
+#endif
+
+    if ( pVBInfo->ModeType >= ModeEGA )
+    {
+        if ( ModeNo > 0x13 )
+        {
+            AdapterMemorySize = 0x40000 ;      /* clear 256k */
+            /* GetDRAMSize( HwDeviceExtension ) ; */
+            XGI_SetMemory( VideoMemoryAddress , AdapterMemorySize , 0 ) ;
+        }
+        else
+        {
+/*
+            pBuffer = VideoMemoryAddress ;
+            for( i = 0 ; i < 0x4000 ; i++ )
+                pBuffer[ i ] = 0x0000 ;
+*/
+        }
+    }
+    else
+    {
+        pBuffer = VideoMemoryAddress ;
+        if ( pVBInfo->ModeType < ModeCGA )
+        {
+/*
+            for ( i = 0 ; i < 0x4000 ; i++ )
+                pBuffer[ i ] = 0x0720 ;
+*/
+        }
+        else
+            XGI_SetMemory( VideoMemoryAddress , 0x8000 , 0 ) ;
+    }
+}
+
+#endif
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLCDAGroup */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLCDAGroup( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo )
+{
+    USHORT RefreshRateTableIndex ;
+    /* USHORT temp ; */
+
+    /* pVBInfo->SelectCRT2Rate = 0 ; */
+
+    pVBInfo->SetFlag |= ProgrammingCRT2 ;
+    RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ;
+    XGI_GetLVDSResInfo(  ModeNo , ModeIdIndex,  pVBInfo ) ;
+    XGI_GetLVDSData( ModeNo , ModeIdIndex , RefreshRateTableIndex,  pVBInfo);
+    XGI_ModCRT1Regs( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+    XGI_SetLVDSRegs( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+    XGI_SetCRT2ECLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLVDSResInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetLVDSResInfo( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO  pVBInfo )
+{
+    USHORT resindex , xres , yres , modeflag ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;   /* si+St_ResInfo */
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;  /* si+Ext_ResInfo */
+    }
+
+
+    /* if ( ModeNo > 0x13 ) */
+    /* modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; */
+    /* else */
+    /* modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; */
+
+    if ( ModeNo <= 0x13 )
+    {
+        resindex = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;   /* si+St_ResInfo */
+    }
+    else
+    {
+        resindex = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;  /* si+Ext_ResInfo */
+    }
+
+    /* resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; */
+
+    if ( ModeNo <= 0x13 )
+    {
+        xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+        yres = pVBInfo->StResInfo[ resindex ].VTotal ;
+    }
+    else
+    {
+        xres = pVBInfo->ModeResInfo[ resindex ].HTotal ;
+        yres = pVBInfo->ModeResInfo[ resindex ].VTotal ;
+    }
+    if ( ModeNo > 0x13 )
+    {
+        if ( modeflag & HalfDCLK )
+            xres = xres << 1 ;
+
+        if ( modeflag & DoubleScanMode )
+            yres = yres << 1 ;
+    }
+    /* if ( modeflag & Charx8Dot ) */
+    /* { */
+
+    if ( xres == 720 )
+        xres = 640 ;
+
+    /* } */
+    pVBInfo->VGAHDE = xres ;
+    pVBInfo->HDE = xres ;
+    pVBInfo->VGAVDE = yres ;
+    pVBInfo->VDE = yres ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLVDSData */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetLVDSData(  USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO  pVBInfo )
+{
+    USHORT tempbx ;
+    XGI330_LVDSDataStruct *LCDPtr = NULL ;
+    XGI330_CHTVDataStruct  *TVPtr = NULL ;
+
+    tempbx = 2 ;
+
+    if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+    {
+        LCDPtr = ( XGI330_LVDSDataStruct * )XGI_GetLcdPtr( tempbx, ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo) ;
+        pVBInfo->VGAHT = LCDPtr->VGAHT ;
+        pVBInfo->VGAVT = LCDPtr->VGAVT ;
+        pVBInfo->HT = LCDPtr->LCDHT ;
+        pVBInfo->VT = LCDPtr->LCDVT ;
+    }
+    if ( pVBInfo->IF_DEF_CH7017 == 1 )
+    {
+        if ( pVBInfo->VBInfo & SetCRT2ToTV )
+        {
+            TVPtr = ( XGI330_CHTVDataStruct * )XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+            pVBInfo->VGAHT = TVPtr->VGAHT ;
+            pVBInfo->VGAVT = TVPtr->VGAVT ;
+            pVBInfo->HT = TVPtr->LCDHT ;
+            pVBInfo->VT = TVPtr->LCDVT ;
+        }
+    }
+
+    if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+    {
+        if ( !( pVBInfo->LCDInfo & ( SetLCDtoNonExpanding | EnableScalingLCD ) ) )
+        {
+            if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) )
+            {
+                pVBInfo->HDE = 1024 ;
+                pVBInfo->VDE = 768 ;
+            }
+            else if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) )
+            {
+                pVBInfo->HDE = 1280 ;
+                pVBInfo->VDE = 1024 ;
+            }
+            else if ( pVBInfo->LCDResInfo == Panel1400x1050 )
+            {
+                pVBInfo->HDE = 1400 ;
+                pVBInfo->VDE = 1050 ;
+            }
+            else
+            {
+                pVBInfo->HDE = 1600 ;
+                pVBInfo->VDE = 1200 ;
+            }
+        }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_ModCRT1Regs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_ModCRT1Regs( USHORT ModeNo , USHORT ModeIdIndex ,
+                        USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo )
+{
+    UCHAR index ;
+    USHORT tempbx , i ;
+    XGI_LVDSCRT1HDataStruct  *LCDPtr = NULL ;
+    XGI_LVDSCRT1VDataStruct  *LCDPtr1 =NULL ;
+    /* XGI330_CHTVDataStruct *TVPtr = NULL ; */
+    XGI_CH7007TV_TimingHStruct *CH7007TV_TimingHPtr = NULL;
+    XGI_CH7007TV_TimingVStruct *CH7007TV_TimingVPtr = NULL;
+
+    if( ModeNo <= 0x13 )
+        index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+    else
+        index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+
+    index= index & IndexMask ;
+
+    if ( ( pVBInfo->IF_DEF_ScaleLCD == 0 ) || ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( !( pVBInfo->LCDInfo & EnableScalingLCD ) ) ) )
+    {
+        tempbx = 0 ;
+
+        if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+        {
+            LCDPtr = ( XGI_LVDSCRT1HDataStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+
+            for( i = 0 ; i < 8 ; i++ )
+                pVBInfo->TimingH[ 0 ].data[ i ] = LCDPtr[ 0 ].Reg[ i ] ;
+        }
+
+        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToTV )
+            {
+                CH7007TV_TimingHPtr = ( XGI_CH7007TV_TimingHStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+
+                for( i = 0 ; i < 8 ; i++ )
+                    pVBInfo->TimingH[ 0 ].data[ i ] = CH7007TV_TimingHPtr[ 0 ].data[ i ] ;
+            }
+        }
+
+        /* if ( pVBInfo->IF_DEF_CH7017 == 1 )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToTV )
+                TVPtr = ( XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+        } */
+
+        XGI_SetCRT1Timing_H(pVBInfo,HwDeviceExtension) ;
+
+        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+        {
+           XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , CH7007TV_TimingHPtr[ 0 ].data[ 8 ] ) ;
+           XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , CH7007TV_TimingHPtr[ 0 ].data[ 9 ] ) ;
+        }
+
+        tempbx = 1 ;
+
+        if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+        {
+            LCDPtr1 = ( XGI_LVDSCRT1VDataStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+            for( i = 0 ; i < 7 ; i++ )
+                pVBInfo->TimingV[ 0 ].data[ i ] = LCDPtr1[ 0 ].Reg[ i ] ;
+        }
+
+        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToTV )
+            {
+                CH7007TV_TimingVPtr = ( XGI_CH7007TV_TimingVStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+
+                for( i = 0 ; i < 7 ; i++ )
+                    pVBInfo->TimingV[ 0 ].data[ i ] = CH7007TV_TimingVPtr[ 0 ].data[ i ] ;
+            }
+        }
+        /* if ( pVBInfo->IF_DEF_CH7017 == 1 )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToTV )
+                TVPtr = ( XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+        } */
+
+        XGI_SetCRT1Timing_V( ModeIdIndex , ModeNo , pVBInfo) ;
+
+        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+        {
+           XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x33 , ~0x01 , CH7007TV_TimingVPtr[ 0 ].data[ 7 ]&0x01 ) ;
+           XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , CH7007TV_TimingVPtr[ 0 ].data[8 ] ) ;
+           XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , CH7007TV_TimingVPtr[ 0 ].data[9 ] ) ;
+
+        }
+    }
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLVDSRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO  pVBInfo )
+{
+    USHORT tempbx , tempax , tempcx , tempdx , push1 , push2 , modeflag ;
+    unsigned long temp , temp1 , temp2 , temp3 , push3 ;
+    XGI330_LCDDataDesStruct  *LCDPtr = NULL ;
+    XGI330_LCDDataDesStruct2  *LCDPtr1 = NULL ;
+
+    if ( ModeNo > 0x13 )
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+    else
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+
+    if ( !( pVBInfo->SetFlag & Win9xDOSMode ) )
+    {
+        if ( ( pVBInfo->IF_DEF_CH7017 == 0 ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
+        {
+            if ( pVBInfo->IF_DEF_OEMUtil == 1 )
+            {
+               tempbx = 8 ;
+               LCDPtr = ( XGI330_LCDDataDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+            }
+
+            if ( ( pVBInfo->IF_DEF_OEMUtil == 0 ) || ( LCDPtr == 0 ) )
+            {
+                tempbx = 3 ;
+                if ( pVBInfo->LCDInfo & EnableScalingLCD )
+                    LCDPtr1 = ( XGI330_LCDDataDesStruct2 * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+                else
+                    LCDPtr = ( XGI330_LCDDataDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+            }
+
+            XGI_GetLCDSync( &tempax , &tempbx ,pVBInfo) ;
+            push1 = tempbx ;
+            push2 = tempax ;
+
+            /* GetLCDResInfo */
+            if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) )
+            {
+                tempax = 1024 ;
+                tempbx = 768 ;
+            }
+            else if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) )
+            {
+                tempax = 1280 ;
+                tempbx = 1024 ;
+            }
+            else if ( pVBInfo->LCDResInfo == Panel1400x1050 )
+            {
+                tempax = 1400 ;
+                tempbx = 1050 ;
+            }
+            else
+            {
+                tempax = 1600 ;
+                tempbx = 1200 ;
+            }
+
+            if ( pVBInfo->LCDInfo & SetLCDtoNonExpanding )
+            {
+                pVBInfo->HDE=tempax;
+                pVBInfo->VDE=tempbx;
+                pVBInfo->VGAHDE=tempax;
+                pVBInfo->VGAVDE=tempbx;
+            }
+
+            if ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( pVBInfo->LCDInfo & EnableScalingLCD ) )
+            {
+                tempax=pVBInfo->HDE;
+                tempbx=pVBInfo->VDE;
+            }
+
+            tempax = pVBInfo->HT ;
+
+            if ( pVBInfo->LCDInfo & EnableScalingLCD )
+                tempbx = LCDPtr1->LCDHDES ;
+            else
+                tempbx = LCDPtr->LCDHDES ;
+
+            tempcx = pVBInfo->HDE ;
+            tempbx = tempbx & 0x0fff ;
+            tempcx += tempbx ;
+
+            if ( tempcx >= tempax )
+                tempcx -= tempax ;
+
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x1A , tempbx & 0x07 ) ;
+
+            tempcx = tempcx >> 3 ;
+            tempbx = tempbx >> 3 ;
+
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x16 , ( USHORT )( tempbx & 0xff ) ) ;
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x17 , ( USHORT )( tempcx & 0xff ) ) ;
+
+            tempax = pVBInfo->HT ;
+
+            if ( pVBInfo->LCDInfo & EnableScalingLCD )
+                tempbx = LCDPtr1->LCDHRS ;
+            else
+                tempbx = LCDPtr->LCDHRS ;
+
+            tempcx = push2 ;
+
+            if ( pVBInfo->LCDInfo & EnableScalingLCD )
+                tempcx = LCDPtr1->LCDHSync ;
+
+            tempcx += tempbx ;
+
+            if ( tempcx >= tempax )
+                tempcx -= tempax ;
+
+            tempax = tempbx & 0x07 ;
+            tempax = tempax >> 5 ;
+            tempcx = tempcx >> 3 ;
+            tempbx = tempbx >> 3 ;
+
+            tempcx &= 0x1f ;
+            tempax |= tempcx ;
+
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x15 , tempax ) ;
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x14 , ( USHORT )( tempbx & 0xff ) ) ;
+
+            tempax = pVBInfo->VT ;
+            if ( pVBInfo->LCDInfo & EnableScalingLCD )
+                tempbx = LCDPtr1->LCDVDES ;
+            else
+                tempbx = LCDPtr->LCDVDES ;
+            tempcx = pVBInfo->VDE ;
+
+            tempbx = tempbx & 0x0fff ;
+            tempcx += tempbx ;
+            if ( tempcx >= tempax )
+                tempcx -= tempax ;
+
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x1b , ( USHORT )( tempbx & 0xff ) ) ;
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x1c , ( USHORT )( tempcx & 0xff ) ) ;
+
+            tempbx = ( tempbx >> 8 ) & 0x07 ;
+            tempcx = ( tempcx >> 8 ) & 0x07 ;
+
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x1d , ( USHORT )( ( tempcx << 3 ) | tempbx ) ) ;
+
+            tempax = pVBInfo->VT ;
+            if ( pVBInfo->LCDInfo & EnableScalingLCD )
+                tempbx = LCDPtr1->LCDVRS ;
+            else
+                tempbx = LCDPtr->LCDVRS ;
+
+            /* tempbx = tempbx >> 4 ; */
+              tempcx = push1 ;
+
+            if ( pVBInfo->LCDInfo & EnableScalingLCD )
+                tempcx = LCDPtr1->LCDVSync ;
+
+            tempcx += tempbx ;
+            if ( tempcx >= tempax )
+                tempcx -= tempax ;
+
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x18 , ( USHORT )( tempbx & 0xff ) ) ;
+            XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , ~0x0f , ( USHORT )( tempcx & 0x0f ) ) ;
+
+            tempax = ( ( tempbx >> 8 ) & 0x07 ) << 3 ;
+
+            tempbx = pVBInfo->VGAVDE ;
+            if ( tempbx != pVBInfo->VDE )
+                tempax |= 0x40 ;
+
+            if ( pVBInfo->LCDInfo & EnableLVDSDDA )
+                tempax |= 0x40 ;
+
+            XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1a , 0x07 , tempax ) ;
+
+            tempcx = pVBInfo->VGAVT ;
+            tempbx = pVBInfo->VDE ;
+            tempax = pVBInfo->VGAVDE ;
+            tempcx -= tempax ;
+
+            temp = tempax ;            /* 0430 ylshieh */
+            temp1 = ( temp << 18 ) / tempbx ;
+
+            tempdx = ( USHORT )( ( temp << 18 ) % tempbx ) ;
+
+            if ( tempdx != 0 )
+            temp1 += 1 ;
+
+            temp2 = temp1 ;
+            push3 = temp2 ;
+
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x37 , ( USHORT )( temp2 & 0xff ) ) ;
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x36 , ( USHORT )( ( temp2 >> 8 ) & 0xff ) ) ;
+
+            tempbx = ( USHORT )( temp2 >> 16 ) ;
+            tempax = tempbx & 0x03 ;
+
+            tempbx = pVBInfo->VGAVDE ;
+            if ( tempbx == pVBInfo->VDE )
+                tempax |= 0x04 ;
+
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x35 , tempax ) ;
+
+            if ( pVBInfo->VBType & VB_XGI301C )
+            {
+                temp2 = push3 ;
+               XGINew_SetReg1( pVBInfo->Part4Port , 0x3c , ( USHORT )( temp2 & 0xff ) ) ;
+               XGINew_SetReg1( pVBInfo->Part4Port , 0x3b , ( USHORT )( ( temp2 >> 8 ) & 0xff ) ) ;
+               tempbx = ( USHORT )( temp2 >> 16 ) ;
+               XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x3a , ~0xc0 , ( USHORT )( ( tempbx & 0xff ) << 6 ) ) ;
+
+                tempcx = pVBInfo->VGAVDE ;
+                if ( tempcx == pVBInfo->VDE )
+                    XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x30 , ~0x0c , 0x00 ) ;
+                else
+                    XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x30 , ~0x0c , 0x08 ) ;
+            }
+
+            tempcx = pVBInfo->VGAHDE ;
+            tempbx = pVBInfo->HDE ;
+
+            temp1 = tempcx << 16 ;
+
+            tempax = ( USHORT )( temp1 / tempbx ) ;
+
+            if ( ( tempbx & 0xffff ) == ( tempcx & 0xffff ) )
+                tempax = 65535 ;
+
+            temp3 = tempax ;
+            temp1 = pVBInfo->VGAHDE << 16 ;
+
+            temp1 /= temp3 ;
+            temp3 = temp3 << 16 ;
+            temp1 -= 1 ;
+
+            temp3 = ( temp3 & 0xffff0000 ) + ( temp1 & 0xffff ) ;
+
+            tempax = ( USHORT )( temp3 & 0xff ) ;
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x1f , tempax ) ;
+
+            temp1 = pVBInfo->VGAVDE << 18 ;
+            temp1 = temp1 / push3 ;
+            tempbx = ( USHORT )( temp1 & 0xffff ) ;
+
+            if ( pVBInfo->LCDResInfo == Panel1024x768 )
+                tempbx -= 1 ;
+
+            tempax = ( ( tempbx >> 8 ) & 0xff ) << 3 ;
+            tempax |= ( USHORT )( ( temp3 >> 8 ) & 0x07 ) ;
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x20 , ( USHORT )( tempax & 0xff ) ) ;
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x21 , ( USHORT )( tempbx & 0xff ) ) ;
+
+            temp3 = temp3 >> 16 ;
+
+            if ( modeflag & HalfDCLK )
+                temp3 = temp3 >> 1 ;
+
+            XGINew_SetReg1(pVBInfo->Part1Port , 0x22 , ( USHORT )( ( temp3 >> 8 ) & 0xff ) ) ;
+            XGINew_SetReg1(pVBInfo->Part1Port , 0x23 , ( USHORT )( temp3 & 0xff ) ) ;
+        }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2ECLK */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT2ECLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO  pVBInfo )
+{
+    UCHAR di_0 , di_1 , tempal ;
+    int i ;
+
+    tempal = XGI_GetVCLKPtr( RefreshRateTableIndex , ModeNo , ModeIdIndex, pVBInfo ) ;
+    XGI_GetVCLKLen( tempal , &di_0 , &di_1, pVBInfo ) ;
+    XGI_GetLCDVCLKPtr( &di_0 , &di_1, pVBInfo ) ;
+
+    for( i = 0 ; i < 4 ; i++ )
+    {
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x31 , ~0x30 , ( USHORT )( 0x10 * i ) ) ;
+        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+        {
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x2b , di_0 ) ;
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x2c , di_1 ) ;
+        }
+        else if ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) )
+        {
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x2e , di_0 ) ;
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x2f , di_1 ) ;
+        }
+        else
+        {
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x2b , di_0 ) ;
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x2c , di_1 ) ;
+        }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_UpdateModeInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_UpdateModeInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo )
+{
+    USHORT tempcl ,
+           tempch ,
+           temp ,
+           tempbl ,
+           tempax ;
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        tempcl = 0 ;
+        tempch = 0 ;
+        temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ;
+
+        if ( !( temp & 0x20 ) )
+        {
+            temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ;
+            if ( temp & 0x80 )
+            {
+                if ( ( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40 ) )
+                    temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) ;
+                else
+                    temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x63 ) ;
+
+                if ( !( temp & 0x40 ) )
+                    tempcl |= ActiveCRT1 ;
+            }
+        }
+
+        temp = XGINew_GetReg1( pVBInfo->Part1Port , 0x2e ) ;
+        temp &= 0x0f ;
+
+        if ( !( temp == 0x08 ) )
+        {
+            tempax = XGINew_GetReg1( pVBInfo->Part1Port , 0x13 ) ;     /* Check ChannelA by Part1_13 [2003/10/03] */
+            if ( tempax & 0x04 )
+                       tempcl = tempcl | ActiveLCD ;
+
+            temp &= 0x05 ;
+
+            if ( !( tempcl & ActiveLCD ) )
+               if ( temp == 0x01 )
+                    tempcl |= ActiveCRT2 ;
+
+            if ( temp == 0x04 )
+                tempcl |= ActiveLCD ;
+
+            if ( temp == 0x05 )
+            {
+                temp = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
+
+                if( !( temp & 0x08 ) )
+                    tempch |= ActiveAVideo ;
+
+                if ( !( temp & 0x04 ) )
+                    tempch |= ActiveSVideo ;
+
+                if ( temp & 0x02 )
+                    tempch |= ActiveSCART ;
+
+                if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+                {
+                    if ( temp & 0x01 )
+                        tempch |= ActiveHiTV ;
+                }
+
+                if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+                {
+                    temp = XGINew_GetReg1( pVBInfo->Part2Port , 0x4d ) ;
+
+                    if ( temp & 0x10 )
+                        tempch |= ActiveYPbPr ;
+                }
+
+                if ( tempch != 0 )
+                    tempcl |= ActiveTV ;
+            }
+        }
+
+        temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ;
+        if ( tempcl & ActiveLCD )
+        {
+            if ( ( pVBInfo->SetFlag & ReserveTVOption ) )
+            {
+                if ( temp & ActiveTV )
+                    tempcl |= ActiveTV ;
+            }
+        }
+        temp = tempcl ;
+        tempbl = ~ModeSwitchStatus ;
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x3d , tempbl , temp ) ;
+
+        if ( !( pVBInfo->SetFlag & ReserveTVOption ) )
+            XGINew_SetReg1( pVBInfo->P3d4 , 0x3e , tempch ) ;
+    }
+    else
+    {
+        return ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVGAType */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetVGAType( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo)
+{
+    /*
+    if ( HwDeviceExtension->jChipType >= XG20 )
+    {
+        pVBInfo->Set_VGAType = XG20;
+    }
+    else if ( HwDeviceExtension->jChipType >= XG40 )
+    {
+        pVBInfo->Set_VGAType = VGA_XGI340 ;
+    }
+    */
+    pVBInfo->Set_VGAType = HwDeviceExtension->jChipType;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVBType */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetVBType(PVB_DEVICE_INFO  pVBInfo)
+{
+    USHORT flag , tempbx , tempah ;
+
+    if ( pVBInfo->IF_DEF_CH7007 == 1 )
+    {
+        pVBInfo->VBType = VB_CH7007 ;
+        return;
+    }
+    if ( pVBInfo->IF_DEF_LVDS == 0 )
+    {
+        tempbx = VB_XGI302B ;
+        flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x00 ) ;
+        if ( flag != 0x02 )
+        {
+            tempbx = VB_XGI301 ;
+            flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) ;
+            if ( flag >= 0xB0 )
+            {
+                tempbx = VB_XGI301B ;
+                if ( flag >= 0xC0 )
+                {
+                    tempbx = VB_XGI301C ;
+                    if ( flag >= 0xD0 )
+                    {
+                        tempbx = VB_XGI301LV ;
+                        if ( flag >= 0xE0 )
+                        {
+                            tempbx = VB_XGI302LV ;
+                            tempah = XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) ;
+                            if ( tempah != 0xFF )
+                                tempbx = VB_XGI301C ;
+                        }
+                    }
+                }
+
+                if ( tempbx & ( VB_XGI301B | VB_XGI302B ) )
+                {
+                    flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x23 ) ;
+
+                    if ( !( flag & 0x02 ) )
+                        tempbx = tempbx | VB_NoLCD ;
+                }
+            }
+        }
+        pVBInfo->VBType = tempbx ;
+    }
+/*
+    else if ( pVBInfo->IF_DEF_CH7017 == 1 )
+        pVBInfo->VBType = VB_CH7017 ;
+    else  //LVDS
+        pVBInfo->VBType = VB_LVDS_NS ;
+*/
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVBInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetVBInfo( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo )
+{
+    USHORT tempax ,
+           push ,
+           tempbx ,
+           temp ,
+           modeflag ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+    }
+
+    pVBInfo->SetFlag = 0 ;
+    pVBInfo->ModeType = modeflag & ModeInfoFlag ;
+    tempbx = 0 ;
+
+    if ( pVBInfo->VBType & 0xFFFF )
+    {
+        temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) ;           /* Check Display Device */
+        tempbx = tempbx | temp ;
+        temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ;
+        push = temp ;
+        push = push << 8 ;
+        tempax = temp << 8 ;
+        tempbx = tempbx | tempax ;
+        temp = ( SetCRT2ToDualEdge | SetCRT2ToYPbPr | SetCRT2ToLCDA | SetInSlaveMode | DisableCRT2Display ) ;
+        temp = 0xFFFF ^ temp ;
+        tempbx &= temp ;
+
+        temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+
+        if ( pVBInfo->IF_DEF_LCDA == 1 )
+        {
+
+            if ( ( pVBInfo->Set_VGAType >= XG20 ) || ( pVBInfo->Set_VGAType >= XG40 ))
+            {
+                if ( pVBInfo->IF_DEF_LVDS == 0 )
+                {
+                    /* if ( ( pVBInfo->VBType & VB_XGI302B ) || ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) */
+                    if ( pVBInfo->VBType & ( VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+                    {
+                        if ( temp & EnableDualEdge )
+                        {
+                            tempbx |= SetCRT2ToDualEdge ;
+
+                            if ( temp & SetToLCDA )
+                                tempbx |= SetCRT2ToLCDA ;
+                        }
+                    }
+                }
+                else if ( pVBInfo->IF_DEF_CH7017 == 1 )
+                {
+                    if ( pVBInfo->VBType & VB_CH7017 )
+                    {
+                        if ( temp & EnableDualEdge )
+                        {
+                            tempbx |= SetCRT2ToDualEdge ;
+
+                            if ( temp & SetToLCDA )
+                                tempbx |= SetCRT2ToLCDA ;
+                        }
+                    }
+                }
+            }
+        }
+
+        if ( pVBInfo->IF_DEF_YPbPr == 1 )
+        {
+            if ( ( ( pVBInfo->IF_DEF_LVDS == 0 ) && ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) )
+            || ( ( pVBInfo->IF_DEF_CH7017 == 1 ) && ( pVBInfo->VBType&VB_CH7017 ) ) || ( (pVBInfo->IF_DEF_CH7007 == 1) && (pVBInfo->VBType&VB_CH7007) ) )    /* [Billy] 07/05/04 */
+            {
+                if ( temp & SetYPbPr ) /* temp = CR38 */
+                {
+                    if ( pVBInfo->IF_DEF_HiVision == 1 )
+                    {
+                        temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;  /* shampoo add for new scratch */
+                        temp &= YPbPrMode ;
+                        tempbx |= SetCRT2ToHiVisionTV ;
+
+                        if ( temp != YPbPrMode1080i ) {
+                            tempbx &= ( ~SetCRT2ToHiVisionTV ) ;
+                            tempbx |= SetCRT2ToYPbPr ; }
+                    }
+
+                    /* tempbx |= SetCRT2ToYPbPr ; */
+                }
+            }
+        }
+
+        tempax = push ;  /* restore CR31 */
+
+        if ( pVBInfo->IF_DEF_LVDS == 0 )
+        {
+            if ( pVBInfo->IF_DEF_YPbPr == 1 )
+            {
+                if ( pVBInfo->IF_DEF_HiVision == 1 )
+                    temp = 0x09FC ;
+                else
+                    temp = 0x097C ;
+            }
+            else
+            {
+                if ( pVBInfo->IF_DEF_HiVision == 1 )
+                    temp = 0x01FC ;
+                else
+                    temp = 0x017C ;
+            }
+        }
+        else   /* 3nd party chip */
+        {
+            if ( pVBInfo->IF_DEF_CH7017 == 1 )
+                temp = ( SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) ;
+            else if ( pVBInfo->IF_DEF_CH7007 == 1 )  /* [Billy] 07/05/03 */
+            {
+                temp = SetCRT2ToTV ;
+            }
+            else
+                temp = SetCRT2ToLCD ;
+        }
+
+        if ( !( tempbx & temp ) )
+        {
+            tempax |= DisableCRT2Display ;
+            tempbx = 0 ;
+        }
+
+        if ( pVBInfo->IF_DEF_LCDA == 1 )       /* Select Display Device */
+        {
+            if ( !( pVBInfo->VBType & VB_NoLCD ) )
+            {
+                if ( tempbx & SetCRT2ToLCDA )
+                {
+                    if ( tempbx & SetSimuScanMode )
+                        tempbx &= ( ~( SetCRT2ToLCD | SetCRT2ToRAMDAC | SwitchToCRT2 ) ) ;
+                    else
+                        tempbx &= ( ~( SetCRT2ToLCD | SetCRT2ToRAMDAC | SetCRT2ToTV | SwitchToCRT2 ) ) ;
+                }
+            }
+        }
+
+        /* shampoo add */
+        if ( !( tempbx & ( SwitchToCRT2 | SetSimuScanMode ) ) )        /* for driver abnormal */
+        {
+            if ( pVBInfo->IF_DEF_CRT2Monitor == 1 )
+            {
+                if ( tempbx & SetCRT2ToRAMDAC )
+                {
+                    tempbx &= ( 0xFF00 | SetCRT2ToRAMDAC | SwitchToCRT2 | SetSimuScanMode ) ;
+                    tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ;
+                }
+            }
+            else
+                tempbx &= ( ~( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) ;
+        }
+
+        if ( !( pVBInfo->VBType & VB_NoLCD ) )
+        {
+            if ( tempbx & SetCRT2ToLCD )
+            {
+                tempbx &= ( 0xFF00 | SetCRT2ToLCD | SwitchToCRT2 | SetSimuScanMode ) ;
+                tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ;
+            }
+        }
+
+        if ( tempbx & SetCRT2ToSCART )
+        {
+            tempbx &= ( 0xFF00 | SetCRT2ToSCART | SwitchToCRT2 | SetSimuScanMode ) ;
+            tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ;
+        }
+
+        if ( pVBInfo->IF_DEF_YPbPr == 1 )
+        {
+            if ( tempbx & SetCRT2ToYPbPr )
+                tempbx &= ( 0xFF00 | SwitchToCRT2 | SetSimuScanMode ) ;
+        }
+
+        if ( pVBInfo->IF_DEF_HiVision == 1 )
+        {
+            if ( tempbx & SetCRT2ToHiVisionTV )
+                tempbx &= ( 0xFF00 | SetCRT2ToHiVisionTV | SwitchToCRT2 | SetSimuScanMode ) ;
+        }
+
+        if ( tempax & DisableCRT2Display )     /* Set Display Device Info */
+        {
+            if ( !( tempbx & ( SwitchToCRT2 | SetSimuScanMode ) ) )
+                tempbx = DisableCRT2Display ;
+        }
+
+        if ( !( tempbx & DisableCRT2Display ) )
+        {
+            if ( ( !( tempbx & DriverMode ) ) || ( !( modeflag & CRT2Mode ) ) )
+            {
+                if ( pVBInfo->IF_DEF_LCDA == 1 )
+               {
+                    if ( !( tempbx & SetCRT2ToLCDA ) )
+                        tempbx |= ( SetInSlaveMode | SetSimuScanMode ) ;
+                }
+
+                if ( pVBInfo->IF_DEF_VideoCapture == 1 )
+                {
+                    if ( ( ( HwDeviceExtension->jChipType == XG40 ) && ( pVBInfo->Set_VGAType == XG40 ) )
+                    || ( ( HwDeviceExtension->jChipType == XG41 ) && ( pVBInfo->Set_VGAType == XG41 ) )
+                    || ( ( HwDeviceExtension->jChipType == XG42 ) && ( pVBInfo->Set_VGAType == XG42 ) )
+                    || ( ( HwDeviceExtension->jChipType == XG45 ) && ( pVBInfo->Set_VGAType == XG45 ) ) )
+                    {
+                        if ( ModeNo <= 13 )
+                        {
+                            if ( !( tempbx & SetCRT2ToRAMDAC ) )       /*CRT2 not need to support*/
+                            {
+                                tempbx &= ( 0x00FF | ( ~SetInSlaveMode ) ) ;
+                                pVBInfo->SetFlag |= EnableVCMode ;
+                            }
+                        }
+                    }
+                }
+            }
+
+            /*LCD+TV can't support in slave mode (Force LCDA+TV->LCDB)*/
+            if ( ( tempbx & SetInSlaveMode ) && ( tempbx & SetCRT2ToLCDA ) )
+            {
+                tempbx ^= ( SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToDualEdge ) ;
+                pVBInfo->SetFlag |= ReserveTVOption ;
+            }
+        }
+    }
+
+    pVBInfo->VBInfo = tempbx ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetTVInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetTVInfo( USHORT ModeNo , USHORT ModeIdIndex ,PVB_DEVICE_INFO  pVBInfo )
+{
+    USHORT temp ,
+           tempbx = 0 ,
+           resinfo = 0 ,
+           modeflag ,
+           index1 ;
+
+    tempbx = 0 ;
+    resinfo = 0 ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToTV )
+    {
+        if ( ModeNo <= 0x13 )
+        {
+            modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;      /* si+St_ModeFlag */
+            resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;        /* si+St_ResInfo */
+        }
+        else
+        {
+            modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+            resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */
+        }
+
+        if ( pVBInfo->VBInfo & SetCRT2ToTV )
+        {
+            temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
+            tempbx = temp;
+            if ( tempbx & SetPALTV )
+            {
+                tempbx &= ( SetCHTVOverScan | SetPALMTV | SetPALNTV | SetPALTV ) ;
+                if ( tempbx & SetPALMTV )
+                    tempbx &= ~SetPALTV ; /* set to NTSC if PAL-M */
+            }
+            else
+                tempbx &= ( SetCHTVOverScan | SetNTSCJ | SetPALTV ) ;
+/*
+            if ( pVBInfo->IF_DEF_LVDS == 0 )
+            {
+                index1 = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; //PAL-M/PAL-N Info
+                temp2 = ( index1 & 0xC0 ) >> 5 ;               //00:PAL, 01:PAL-M, 10:PAL-N
+                tempbx |= temp2 ;
+                if ( temp2 & 0x02 )          //PAL-M
+                    tempbx &= ( ~SetPALTV ) ;
+            }
+*/
+        }
+
+        if ( pVBInfo->IF_DEF_CH7017 == 1 )
+        {
+            tempbx = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
+
+            if ( tempbx & TVOverScan )
+                tempbx |= SetCHTVOverScan ;
+        }
+
+        if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 07/05/04 */
+        {
+            tempbx = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
+
+            if ( tempbx & TVOverScan )
+            {
+                tempbx |= SetCHTVOverScan ;
+            }
+        }
+
+
+        if ( pVBInfo->IF_DEF_LVDS == 0 )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToSCART )
+                tempbx |= SetPALTV ;
+        }
+
+        if ( pVBInfo->IF_DEF_YPbPr == 1 )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+            {
+                index1 = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
+                index1 &= YPbPrMode ;
+
+                if ( index1 == YPbPrMode525i )
+                    tempbx |= SetYPbPrMode525i ;
+
+                if ( index1 == YPbPrMode525p )
+                    tempbx = tempbx | SetYPbPrMode525p;
+                if ( index1 == YPbPrMode750p)
+                    tempbx = tempbx | SetYPbPrMode750p;
+            }
+        }
+
+        if ( pVBInfo->IF_DEF_HiVision == 1 )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+            {
+                tempbx = tempbx | SetYPbPrMode1080i | SetPALTV ;
+            }
+        }
+
+        if ( pVBInfo->IF_DEF_LVDS == 0 )
+        {      /* shampoo */
+            if ( ( pVBInfo->VBInfo & SetInSlaveMode ) && ( !( pVBInfo->VBInfo & SetNotSimuMode ) ) )
+                tempbx |= TVSimuMode ;
+
+            if ( !( tempbx & SetPALTV ) && ( modeflag > 13 ) && ( resinfo == 8 ) ) /* NTSC 1024x768, */
+                tempbx |= NTSC1024x768 ;
+
+            tempbx |= RPLLDIV2XO ;
+
+            if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+            {
+                if ( pVBInfo->VBInfo & SetInSlaveMode )
+                    tempbx &=( ~RPLLDIV2XO ) ;
+            }
+            else
+            {
+                if ( tempbx & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
+                    tempbx &= ( ~RPLLDIV2XO ) ;
+                else if ( !( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) )
+                {
+                    if ( tempbx & TVSimuMode )
+                        tempbx &= ( ~RPLLDIV2XO ) ;
+                }
+            }
+        }
+    }
+    pVBInfo->TVInfo = tempbx ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLCDInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_GetLCDInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT temp ,
+           tempax ,
+           tempbx ,
+           modeflag ,
+           resinfo = 0 ,
+           LCDIdIndex ;
+
+    pVBInfo->LCDResInfo = 0 ;
+    pVBInfo->LCDTypeInfo = 0 ;
+    pVBInfo->LCDInfo = 0 ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;  /* si+St_ModeFlag // */
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+        resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo// */
+    }
+
+    temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ; /* Get LCD Res.Info */
+    tempbx = temp & 0x0F ;
+
+    if ( tempbx == 0 )
+        tempbx = Panel1024x768 ; /* default */
+
+    /* LCD75 [2003/8/22] Vicent */
+    if ( ( tempbx == Panel1024x768 ) || ( tempbx == Panel1280x1024 ) )
+    {
+        if ( pVBInfo->VBInfo & DriverMode )
+        {
+            tempax = XGINew_GetReg1( pVBInfo->P3d4 , 0x33 ) ;
+            if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+                tempax &= 0x0F ;
+            else
+                tempax = tempax >> 4 ;
+
+            if ( ( resinfo == 6 ) || ( resinfo == 9 ) )
+            {
+                if ( tempax >= 3 )
+                   tempbx |= PanelRef75Hz ;
+            }
+            else if ( ( resinfo == 7 ) || ( resinfo == 8 ) )
+            {
+               if ( tempax >= 4 )
+                   tempbx |= PanelRef75Hz ;
+            }
+        }
+    }
+
+    pVBInfo->LCDResInfo = tempbx ;
+
+    /* End of LCD75 */
+
+    if( pVBInfo->IF_DEF_OEMUtil == 1 )
+    {
+        pVBInfo->LCDTypeInfo = ( temp & 0xf0 ) >> 4 ;
+    }
+
+    if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
+    {
+        return 0;
+    }
+
+    tempbx = 0 ;
+
+    temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
+
+    temp &= ( ScalingLCD | LCDNonExpanding | LCDSyncBit | SetPWDEnable ) ;
+
+    if ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( temp & LCDNonExpanding ) )
+        temp &= ~EnableScalingLCD ;
+
+    tempbx |= temp ;
+
+    LCDIdIndex = XGI_GetLCDCapPtr1(pVBInfo) ;
+
+    tempax = pVBInfo->LCDCapList[ LCDIdIndex ].LCD_Capability ;
+
+    if ( pVBInfo->IF_DEF_LVDS == 0 )   /* shampoo */
+    {
+        if ( ( ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) && ( tempax & LCDDualLink ) )
+        {
+            tempbx |= SetLCDDualLink ;
+        }
+    }
+
+    if ( pVBInfo->IF_DEF_CH7017 == 1 )
+    {
+        if ( tempax & LCDDualLink )
+        {
+            tempbx |= SetLCDDualLink ;
+        }
+    }
+
+    if ( pVBInfo->IF_DEF_LVDS == 0 )
+    {
+        if ( ( pVBInfo->LCDResInfo == Panel1400x1050 ) && ( pVBInfo->VBInfo & SetCRT2ToLCD ) && ( ModeNo > 0x13 ) && ( resinfo == 9 ) && ( !( tempbx & EnableScalingLCD ) ) )
+            tempbx |= SetLCDtoNonExpanding ;   /* set to center in 1280x1024 LCDB for Panel1400x1050 */
+    }
+
+/*
+    if ( tempax & LCDBToA )
+    {
+        tempbx |= SetLCDBToA ;
+    }
+*/
+
+    if ( pVBInfo->IF_DEF_ExpLink == 1 )
+    {
+        if ( modeflag & HalfDCLK )
+        {
+            /* if ( !( pVBInfo->LCDInfo&LCDNonExpanding ) ) */
+            if ( !( tempbx & SetLCDtoNonExpanding ) )
+            {
+                tempbx |= EnableLVDSDDA ;
+            }
+            else
+            {
+                if ( ModeNo > 0x13 )
+                {
+                    if ( pVBInfo->LCDResInfo == Panel1024x768 )
+                    {
+                        if ( resinfo == 4 )
+                        {                                /* 512x384  */
+                            tempbx |= EnableLVDSDDA ;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if ( pVBInfo->VBInfo & SetInSlaveMode )
+    {
+        if ( pVBInfo->VBInfo & SetNotSimuMode )
+        {
+            tempbx |= LCDVESATiming ;
+        }
+    }
+    else
+    {
+        tempbx |= LCDVESATiming ;
+    }
+
+    pVBInfo->LCDInfo = tempbx ;
+
+    if ( pVBInfo->IF_DEF_PWD == 1 )
+    {
+        if ( pVBInfo->LCDInfo & SetPWDEnable )
+        {
+            if ( ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) )
+            {
+                if ( !( tempax & PWDEnable ) )
+                {
+                    pVBInfo->LCDInfo &= ~SetPWDEnable ;
+                }
+            }
+        }
+    }
+
+    if ( pVBInfo->IF_DEF_LVDS == 0 )
+    {
+        if ( tempax & ( LockLCDBToA | StLCDBToA ) )
+        {
+            if ( pVBInfo->VBInfo & SetInSlaveMode )
+            {
+                if ( !( tempax & LockLCDBToA ) )
+                {
+                    if ( ModeNo <= 0x13 )
+                    {
+                        pVBInfo->VBInfo &= ~( SetSimuScanMode | SetInSlaveMode | SetCRT2ToLCD ) ;
+                        pVBInfo->VBInfo |= SetCRT2ToLCDA | SetCRT2ToDualEdge ;
+                    }
+                }
+            }
+        }
+    }
+
+/*
+    if ( pVBInfo->IF_DEF_LVDS == 0 )
+    {
+        if ( tempax & ( LockLCDBToA | StLCDBToA ) )
+        {
+            if ( pVBInfo->VBInfo & SetInSlaveMode )
+            {
+                if ( !( ( !( tempax & LockLCDBToA ) ) && ( ModeNo > 0x13 ) ) )
+                {
+                    pVBInfo->VBInfo&=~(SetSimuScanMode|SetInSlaveMode|SetCRT2ToLCD);
+                    pVBInfo->VBInfo|=SetCRT2ToLCDA|SetCRT2ToDualEdge;
+                }
+            }
+        }
+    }
+*/
+
+    return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SearchModeID */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_SearchModeID( USHORT ModeNo , USHORT *ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+
+#ifdef TC
+
+    if ( ModeNo <= 5 )
+        ModeNo |= 1 ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
+        for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+        {
+            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
+                break ;
+            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
+                return( FALSE ) ;
+        }
+
+        VGA_INFO = ( PUCHAR )MK_FP( 0 , 0x489 ) ;
+
+        if ( ModeNo == 0x07 )
+        {
+            if ( ( *VGA_INFO & 0x10 ) != 0 )
+                ( *ModeIdIndex )++ ; /* 400 lines */
+            /* else 350 lines */
+        }
+
+        if ( ModeNo <= 3 )
+        {
+            if ( ( *VGA_INFO & 0x80 ) == 0 )
+            {
+                ( *ModeIdIndex )++ ;
+                if ( ( *VGA_INFO & 0x10 ) != 0 )
+                    ( *ModeIdIndex )++ ; /* 400 lines */
+                /* else 350 lines */
+            }
+            /* else 200 lines */
+        }
+    }
+    else
+    {
+        /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
+        for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+        {
+            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
+                break ;
+            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
+                return( FALSE ) ;
+        }
+    }
+
+
+#endif
+
+#ifdef WIN2000
+
+    if ( ModeNo <= 5 )
+        ModeNo |= 1 ;
+    if ( ModeNo <= 0x13 )
+    {
+        /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
+        for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+        {
+            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
+                break ;
+            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
+                return( FALSE ) ;
+        }
+
+        if ( ModeNo == 0x07 )
+            ( *ModeIdIndex )++ ; /* 400 lines */
+
+        if ( ModeNo <=3 )
+            ( *ModeIdIndex ) += 2 ; /* 400 lines */
+        /* else 350 lines */
+    }
+    else
+    {
+        /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
+        for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+        {
+            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
+                break ;
+            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
+                return( FALSE ) ;
+        }
+    }
+
+#endif
+
+#ifdef LINUX /* chiawen for linux solution */
+
+    if ( ModeNo <= 5 )
+        ModeNo |= 1 ;
+    if ( ModeNo <= 0x13 )
+    {
+        /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
+        for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+        {
+            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
+                break ;
+            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
+                return( FALSE ) ;
+        }
+
+        if ( ModeNo == 0x07 )
+            ( *ModeIdIndex )++ ; /* 400 lines */
+
+        if ( ModeNo <= 3 )
+            ( *ModeIdIndex ) += 2 ; /* 400 lines */
+        /* else 350 lines */
+    }
+    else
+    {
+        /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
+        for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+        {
+            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
+                break ;
+            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
+                return( FALSE ) ;
+        }
+    }
+
+#endif
+
+    return( TRUE ) ;
+}
+
+
+
+
+/* win2000 MM adapter not support standard mode! */
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT memorysize ,
+           modeflag ,
+           temp ,
+           temp1 ,
+           tmp ;
+
+/*  if ( ( HwDeviceExtension->jChipType == XGI_650 ) ||
+         ( HwDeviceExtension->jChipType == XGI_650M ) )
+    {
+        return( TRUE ) ;
+    } */
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+    }
+    else  {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+    }
+
+    /* ModeType = modeflag&ModeInfoFlag ; // Get mode type */
+
+    memorysize = modeflag & MemoryInfoFlag ;
+    memorysize = memorysize > MemorySizeShift ;
+    memorysize++ ;                                     /* Get memory size */
+
+    temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;    /* Get DRAM Size */
+    tmp = temp ;
+
+    if ( HwDeviceExtension->jChipType == XG40 )
+    {
+        temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ;                /* memory size per channel SR14[7:4] */
+        if ( ( tmp & 0x0c ) == 0x0C )                  /* Qual channels */
+        {
+            temp <<= 2 ;
+        }
+        else if ( ( tmp & 0x0c ) == 0x08 )             /* Dual channels */
+        {
+            temp <<= 1 ;
+        }
+    }
+    else if ( HwDeviceExtension->jChipType == XG42 )
+    {
+       temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ;         /* memory size per channel SR14[7:4] */
+        if ( ( tmp & 0x04 ) == 0x04 )                  /* Dual channels */
+        {
+            temp <<= 1 ;
+        }
+    }
+    else if ( HwDeviceExtension->jChipType == XG45 )
+    {
+       temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ;         /* memory size per channel SR14[7:4] */
+       if ( ( tmp & 0x0c ) == 0x0C )                   /* Qual channels */
+        {
+            temp <<= 2 ;
+        }
+        else if ( ( tmp & 0x0c ) == 0x08 )             /* triple channels */
+        {
+            temp1 = temp ;
+            temp <<= 1 ;
+            temp += temp1 ;
+        }
+        else if ( ( tmp & 0x0c ) == 0x04 )             /* Dual channels */
+        {
+            temp <<= 1 ;
+        }
+    }
+    if ( temp < memorysize )
+        return( FALSE ) ;
+    else
+        return( TRUE ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_IsLowResolution */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+/*void XGINew_IsLowResolution( USHORT ModeNo , USHORT ModeIdIndex, BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT data ;
+    USHORT ModeFlag ;
+
+    data = XGINew_GetReg1( pVBInfo->P3c4 , 0x0F ) ;
+    data &= 0x7F ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x0F , data ) ;
+
+    if ( ModeNo > 0x13 )
+    {
+        ModeFlag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+        if ( ( ModeFlag & HalfDCLK ) && ( ModeFlag & DoubleScanMode ) )
+        {
+            data = XGINew_GetReg1( pVBInfo->P3c4 , 0x0F ) ;
+            data |= 0x80 ;
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x0F , data ) ;
+            data = XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ;
+            data &= 0xF7 ;
+            XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ;
+        }
+    }
+}
+
+*/
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisplayOn */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_DisplayOn( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo )
+{
+
+    XGINew_SetRegANDOR(pVBInfo->P3c4,0x01,0xDF,0x00);
+    if ( pXGIHWDE->jChipType == XG21 )
+    {
+       if ( pVBInfo->IF_DEF_LVDS == 1 )
+       {
+         if (!(XGI_XG21GetPSCValue( pVBInfo )&0x1))
+         {
+            XGI_XG21BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
+            XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
+         }
+         if (!(XGI_XG21GetPSCValue( pVBInfo )&0x20))
+         {
+            XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
+         }
+         XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
+         XGI_XG21BLSignalVDD( 0x02 , 0x02, pVBInfo ) ; /* LVDS backlight on */
+       }
+       else
+       {
+            XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* DVO/DVI signal on */
+       }
+
+    }
+
+    if (pVBInfo->IF_DEF_CH7007 == 1) /* [Billy] 07/05/23 For CH7007 */
+    {
+#ifdef WIN2000
+       if ( IsCH7007TVMode( pVBInfo ) )
+       {
+           TurnOnCH7007(pXGIHWDE->pDevice) ; /* 07/05/28 */
+       }
+#endif
+
+    }
+
+
+    if ( pXGIHWDE->jChipType == XG27 )
+    {
+       if ( pVBInfo->IF_DEF_LVDS == 1 )
+       {
+         if (!(XGI_XG27GetPSCValue( pVBInfo )&0x1))
+         {
+            XGI_XG27BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
+            XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
+         }
+         if (!(XGI_XG27GetPSCValue( pVBInfo )&0x20))
+         {
+            XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
+         }
+         XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
+         XGI_XG27BLSignalVDD( 0x02 , 0x02, pVBInfo ) ; /* LVDS backlight on */
+       }
+       else
+       {
+            XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* DVO/DVI signal on */
+       }
+
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisplayOff */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_DisplayOff( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo )
+{
+
+    if ( pXGIHWDE->jChipType == XG21 )
+    {
+       if ( pVBInfo->IF_DEF_LVDS == 1 )
+       {
+         XGI_XG21BLSignalVDD( 0x02 , 0x00, pVBInfo ) ; /* LVDS backlight off */
+         XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
+       }
+       else
+       {
+            XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* DVO/DVI signal off */
+       }
+    }
+
+    if (pVBInfo->IF_DEF_CH7007 == 1) /*[Billy] 07/05/23 For CH7007 */
+    {
+       /* if( IsCH7007TVMode( pVBInfo ) == 0 ) */
+       {
+#ifdef WIN2000
+         TurnOffCH7007(pXGIHWDE->pDevice) ;  /* 07/05/28 */
+#endif
+       }
+    }
+
+
+    if ( pXGIHWDE->jChipType == XG27 )
+    {
+       if ((XGI_XG27GetPSCValue( pVBInfo )&0x2))
+       {
+         XGI_XG27BLSignalVDD( 0x02 , 0x00, pVBInfo ) ; /* LVDS backlight off */
+         XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
+       }
+
+       if ( pVBInfo->IF_DEF_LVDS == 0 )
+       {
+            XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* DVO/DVI signal off */
+       }
+    }
+
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xDF , 0x20 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_WaitDisply */
+/* Input : */
+/* Output : */
+/* Description : chiawen for sensecrt1 */
+/* --------------------------------------------------------------------- */
+void XGI_WaitDisply( PVB_DEVICE_INFO pVBInfo )
+{
+    while( ( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) )
+        break ;
+
+    while( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) )
+        break ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SenseCRT1 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+
+void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR CRTCData[ 17 ] = { 0x5F , 0x4F , 0x50 , 0x82 , 0x55 , 0x81 ,
+                             0x0B , 0x3E , 0xE9 , 0x0B , 0xDF , 0xE7 ,
+                             0x04 , 0x00 , 0x00 , 0x05 , 0x00 } ;
+
+    UCHAR SR01 = 0 , SR1F = 0 , SR07 = 0 , SR06 = 0 ;
+
+    UCHAR CR17 , CR63 , SR31 ;
+    USHORT temp ;
+    UCHAR DAC_TEST_PARMS[ 3 ] = { 0x0F , 0x0F , 0x0F } ;
+
+    int i ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
+
+    /* [2004/05/06] Vicent to fix XG42 single LCD sense to CRT+LCD */
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x4A ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x53 , ( UCHAR )( XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) | 0x02 ) ) ;
+
+    SR31 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) ;
+    CR63 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x63 ) ;
+    SR01 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ;
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , ( UCHAR )( SR01 & 0xDF ) ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x63 , ( UCHAR )( CR63 & 0xBF ) ) ;
+
+    CR17 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x17 , ( UCHAR )( CR17 | 0x80 ) ) ;
+
+    SR1F = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , ( UCHAR )( SR1F | 0x04 ) ) ;
+
+    SR07 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x07 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x07 , ( UCHAR )( SR07 & 0xFB ) ) ;
+    SR06 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x06 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x06 , ( UCHAR )( SR06 & 0xC3 ) ) ;
+
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , 0x00 ) ;
+
+    for( i = 0 ; i < 8 ; i++ )
+        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )i , CRTCData[ i ] ) ;
+
+    for( i = 8 ; i < 11 ; i++ )
+        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 8 ) , CRTCData[ i ] ) ;
+
+    for( i = 11 ; i < 13 ; i++ )
+        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 4 ) , CRTCData[ i ] ) ;
+
+    for( i = 13 ; i < 16 ; i++ )
+        XGINew_SetReg1( pVBInfo->P3c4 , ( USHORT )( i - 3 ) , CRTCData[ i ] ) ;
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x0E , ( UCHAR )( CRTCData[ 16 ] & 0xE0 ) ) ;
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , 0x00 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x1B ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE1 ) ;
+
+    XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ;
+
+    for( i = 0 ; i < 256 ; i++ )
+    {
+        XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 0 ] ) ;
+        XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 1 ] ) ;
+        XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 2 ] ) ;
+    }
+
+    XGI_VBLongWait( pVBInfo ) ;
+    XGI_VBLongWait( pVBInfo ) ;
+    XGI_VBLongWait( pVBInfo ) ;
+
+    XGINew_LCD_Wait_Time( 0x01 , pVBInfo ) ;
+
+    XGI_WaitDisply( pVBInfo ) ;
+    temp = XGINew_GetReg2( pVBInfo->P3c2 ) ;
+
+    if( temp & 0x10 )
+    {
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xDF , 0x20 ) ;
+    }
+    else
+    {
+        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xDF , 0x00 ) ;
+    }
+
+    /* alan, avoid display something, set BLACK DAC if not restore DAC */
+    XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ;
+
+    for( i = 0 ; i < 256 ; i++ )
+    {
+      XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ;
+      XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ;
+      XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ;
+    }
+
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , SR01 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x63 , CR63 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , SR31 ) ;
+
+    /* [2004/05/11] Vicent */
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x53 , ( UCHAR )( XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) & 0xFD ) ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , ( UCHAR ) SR1F ) ;
+}
+
+
+
+
+
+#ifdef TC
+/* --------------------------------------------------------------------- */
+/* Function : INT1AReturnCode */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int INT1AReturnCode( union REGS regs )
+{
+    if ( regs.x.cflag )
+    {
+        /* printf( "Error to find pci device!\n" ) ; */
+        return( 1 ) ;
+    }
+
+    switch(regs.h.ah)
+    {
+        case 0: return 0;
+            break ;
+        case 0x81:
+            printf( "Function not support\n" ) ;
+            break ;
+        case 0x83:
+            printf( "bad vendor id\n" ) ;
+            break ;
+        case 0x86:
+            printf( "device not found\n" ) ;
+            break ;
+        case 0x87:
+            printf( "bad register number\n" ) ;
+            break ;
+        case 0x88:
+            printf( "set failed\n" ) ;
+            break ;
+        case 0x89:
+            printf( "buffer too small" ) ;
+            break ;
+        default:
+            break ;
+    }
+    return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : FindPCIIOBase */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+unsigned FindPCIIOBase( unsigned index , unsigned deviceid )
+{
+    union REGS regs ;
+
+    regs.h.ah = 0xb1 ; /* PCI_FUNCTION_ID */
+    regs.h.al = 0x02 ; /* FIND_PCI_DEVICE */
+    regs.x.cx = deviceid ;
+    regs.x.dx = 0x1039 ;
+    regs.x.si = index ;        /* find n-th device */
+
+    int86( 0x1A , &regs , &regs ) ;
+
+    if ( INT1AReturnCode( regs ) != 0 )
+        return( 0 ) ;
+
+    /* regs.h.bh bus number */
+    /* regs.h.bl device number */
+    regs.h.ah = 0xb1 ;  /* PCI_FUNCTION_ID */
+    regs.h.al = 0x09 ;  /* READ_CONFIG_WORD */
+    regs.x.cx = deviceid ;
+    regs.x.dx = 0x1039 ;
+    regs.x.di = 0x18 ;  /* register number */
+    int86( 0x1A , &regs , &regs ) ;
+
+    if ( INT1AReturnCode( regs ) != 0 )
+        return( 0 ) ;
+
+    return( regs.x.cx ) ;
+}
+
+#endif
+
+
+
+#ifdef TC
+/* --------------------------------------------------------------------- */
+/* Function : main */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void main(int argc, char *argv[])
+{
+    XGI_HW_DEVICE_INFO HwDeviceExtension ;
+    USHORT temp ;
+    USHORT ModeNo ;
+
+    /* HwDeviceExtension.pjVirtualRomBase =(PUCHAR) MK_FP(0xC000,0); */
+    /* HwDeviceExtension.pjVideoMemoryAddress = (PUCHAR)MK_FP(0xA000,0); */
+
+
+    HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 ,0x6300 ) & 0xFF80 ) + 0x30 ;
+    HwDeviceExtension.jChipType = XGI_340 ;
+
+
+
+    /* HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 , 0x5315 ) & 0xFF80 ) + 0x30 ; */
+
+    HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 , 0x330 ) & 0xFF80 ) + 0x30 ;
+    HwDeviceExtension.jChipType = XGI_340 ;
+
+
+    HwDeviceExtension.ujVBChipID = VB_CHIP_301 ;
+    StrCpy(HwDeviceExtension.szVBIOSVer , "0.84" ) ;
+    HwDeviceExtension.bSkipDramSizing = FALSE ;
+    HwDeviceExtension.ulVideoMemorySize = 0 ;
+
+    if ( argc == 2 )
+    {
+        ModeNo = atoi( argv[ 1 ] ) ;
+    }
+    else
+    {
+        ModeNo = 0x2e ;
+        /* ModeNo = 0x37 ; 1024x768x 4bpp */
+        /* ModeNo = 0x38 ; 1024x768x 8bpp */
+        /* ModeNo = 0x4A ; 1024x768x 16bpp */
+        /* ModeNo = 0x47 ; 800x600x 16bpp */
+    }
+
+    /* XGIInitNew( &HwDeviceExtension ) ; */
+    XGISetModeNew( &HwDeviceExtension , ModeNo ) ;
+}
+#endif
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_WaitDisplay */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_WaitDisplay( PVB_DEVICE_INFO pVBInfo )
+{
+    while( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) ) ;
+
+    while( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) ;
+}
+
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2Group301 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_SetCRT2Group301( USHORT ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempbx ,
+           ModeIdIndex ,
+           RefreshRateTableIndex ;
+
+    tempbx=pVBInfo->VBInfo ;
+    pVBInfo->SetFlag |= ProgrammingCRT2 ;
+    XGI_SearchModeID( ModeNo , &ModeIdIndex,  pVBInfo ) ;
+    pVBInfo->SelectCRT2Rate = 4 ;
+    RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ;
+    XGI_SaveCRT2Info( ModeNo, pVBInfo ) ;
+    XGI_GetCRT2ResInfo( ModeNo , ModeIdIndex, pVBInfo) ;
+    XGI_GetCRT2Data( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+    XGI_PreSetGroup1( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
+    XGI_SetGroup1( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
+    XGI_SetLockRegs( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
+    XGI_SetGroup2(  ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+    XGI_SetLCDRegs(ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
+    XGI_SetTap4Regs(pVBInfo) ;
+    XGI_SetGroup3(ModeNo, ModeIdIndex, pVBInfo);
+    XGI_SetGroup4( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+    XGI_SetCRT2VCLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+    XGI_SetGroup5( ModeNo , ModeIdIndex, pVBInfo) ;
+    XGI_AutoThreshold( pVBInfo) ;
+    return 1 ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_AutoThreshold */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_AutoThreshold(  PVB_DEVICE_INFO pVBInfo )
+{
+    if ( !( pVBInfo->SetFlag & Win9xDOSMode ) )
+      XGINew_SetRegOR( pVBInfo->Part1Port , 0x01 , 0x40 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SaveCRT2Info */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SaveCRT2Info( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT temp1 ,
+           temp2 ;
+
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x34 , ModeNo ) ;  /* reserve CR34 for CRT1 Mode No */
+    temp1 = ( pVBInfo->VBInfo&SetInSlaveMode ) >> 8 ;
+    temp2 = ~( SetInSlaveMode >> 8 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x31 , temp2 , temp1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetCRT2ResInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetCRT2ResInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT xres ,
+           yres ,
+           modeflag ,
+           resindex ;
+
+    resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo) ;
+    if ( ModeNo <= 0x13 )
+    {
+        xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+        yres = pVBInfo->StResInfo[ resindex ].VTotal ;
+     /* modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; si+St_ResInfo */
+    }
+    else
+    {
+        xres = pVBInfo->ModeResInfo[ resindex ].HTotal ;                       /* xres->ax */
+        yres = pVBInfo->ModeResInfo[ resindex ].VTotal ;                       /* yres->bx */
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ;          /* si+St_ModeFlag */
+
+/*        if ( pVBInfo->IF_DEF_FSTN )
+        {
+            xres *= 2 ;
+            yres *= 2 ;
+        }
+        else
+        {
+*/
+            if ( modeflag & HalfDCLK )
+                xres *= 2;
+
+            if ( modeflag & DoubleScanMode )
+                yres *= 2 ;
+/* } */
+    }
+
+    if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+    {
+        if ( pVBInfo->IF_DEF_LVDS == 0 )
+        {
+            if ( pVBInfo->LCDResInfo == Panel1600x1200 )
+            {
+                if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+                {
+                    if ( yres == 1024 )
+                        yres = 1056 ;
+               }
+            }
+
+            if ( pVBInfo->LCDResInfo == Panel1280x1024 )
+            {
+               if ( yres == 400 )
+                   yres = 405 ;
+               else if ( yres == 350 )
+                   yres = 360 ;
+
+               if ( pVBInfo->LCDInfo & LCDVESATiming )
+               {
+                   if ( yres == 360 )
+                       yres = 375 ;
+               }
+            }
+
+            if ( pVBInfo->LCDResInfo == Panel1024x768 )
+            {
+               if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+               {
+                   if ( !( pVBInfo->LCDInfo & LCDNonExpanding ) )
+                   {
+                       if ( yres == 350 )
+                           yres = 357 ;
+                       else if ( yres == 400 )
+                           yres = 420 ;
+                       else if ( yres == 480 )
+                           yres = 525 ;
+                   }
+                }
+            }
+        }
+
+        if ( xres == 720 )
+            xres = 640 ;
+    }
+
+    pVBInfo->VGAHDE = xres ;
+    pVBInfo->HDE = xres ;
+    pVBInfo->VGAVDE = yres ;
+    pVBInfo->VDE = yres ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_IsLCDDualLink */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_IsLCDDualLink( PVB_DEVICE_INFO pVBInfo )
+{
+
+    if ( ( ( ( pVBInfo->VBInfo & SetCRT2ToLCD ) | SetCRT2ToLCDA ) ) && ( pVBInfo->LCDInfo & SetLCDDualLink ) ) /* shampoo0129 */
+        return ( 1 ) ;
+
+    return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetCRT2Data */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetCRT2Data(  USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempax = 0,
+           tempbx ,
+           modeflag ,
+           resinfo ;
+
+    XGI_LCDDataStruct *LCDPtr = NULL ;
+    XGI_TVDataStruct  *TVPtr = NULL ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;      /* si+St_ResInfo */
+        resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;     /* si+Ext_ResInfo */
+        resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+    }
+
+    pVBInfo->NewFlickerMode = 0 ;
+    pVBInfo->RVBHRS = 50 ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+    {
+        XGI_GetRAMDAC2DATA( ModeNo , ModeIdIndex , RefreshRateTableIndex,pVBInfo ) ;
+        return ;
+    }
+
+    tempbx = 4 ;
+
+    if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+    {
+        LCDPtr = (XGI_LCDDataStruct* )XGI_GetLcdPtr( tempbx, ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+
+        pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX ;
+        pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT ;
+        pVBInfo->VGAHT = LCDPtr->VGAHT ;
+        pVBInfo->VGAVT = LCDPtr->VGAVT ;
+        pVBInfo->HT = LCDPtr->LCDHT ;
+        pVBInfo->VT = LCDPtr->LCDVT ;
+
+        if ( pVBInfo->LCDResInfo == Panel1024x768 )
+        {
+            tempax = 1024 ;
+            tempbx = 768 ;
+
+            if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+            {
+                if ( pVBInfo->VGAVDE == 357 )
+                    tempbx = 527 ;
+               else if ( pVBInfo->VGAVDE == 420 )
+                   tempbx = 620 ;
+               else if ( pVBInfo->VGAVDE == 525 )
+                   tempbx = 775 ;
+               else if ( pVBInfo->VGAVDE == 600 )
+                   tempbx = 775 ;
+                /* else if(pVBInfo->VGAVDE==350) tempbx=560; */
+                /* else if(pVBInfo->VGAVDE==400) tempbx=640; */
+               else
+                 tempbx = 768 ;
+            }
+            else
+                tempbx = 768 ;
+        }
+        else if ( pVBInfo->LCDResInfo == Panel1024x768x75 )
+        {
+            tempax = 1024 ;
+            tempbx = 768 ;
+        }
+        else if ( pVBInfo->LCDResInfo == Panel1280x1024 )
+        {
+            tempax = 1280 ;
+            if ( pVBInfo->VGAVDE == 360 )
+                tempbx = 768 ;
+            else if ( pVBInfo->VGAVDE == 375 )
+                tempbx = 800 ;
+            else if ( pVBInfo->VGAVDE == 405 )
+                tempbx = 864 ;
+            else
+                tempbx = 1024 ;
+        }
+        else if ( pVBInfo->LCDResInfo == Panel1280x1024x75 )
+        {
+            tempax = 1280 ;
+            tempbx = 1024 ;
+        }
+        else if ( pVBInfo->LCDResInfo == Panel1280x960 )
+        {
+            tempax = 1280 ;
+            if ( pVBInfo->VGAVDE == 350 )
+                tempbx = 700 ;
+            else if ( pVBInfo->VGAVDE == 400 )
+                tempbx = 800 ;
+            else if ( pVBInfo->VGAVDE == 1024 )
+                tempbx = 960 ;
+            else
+                tempbx = 960 ;
+        }
+        else if ( pVBInfo->LCDResInfo == Panel1400x1050 )
+        {
+            tempax = 1400 ;
+            tempbx = 1050 ;
+
+            if ( pVBInfo->VGAVDE == 1024 )
+            {
+                tempax = 1280 ;
+                tempbx = 1024 ;
+            }
+        }
+        else if ( pVBInfo->LCDResInfo == Panel1600x1200 )
+        {
+            tempax = 1600 ;
+            tempbx = 1200 ;  /* alan 10/14/2003 */
+            if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+            {
+              if ( pVBInfo->VGAVDE == 350 )
+                tempbx = 875 ;
+              else if ( pVBInfo->VGAVDE == 400 )
+                tempbx = 1000 ;
+            }
+        }
+
+        if ( pVBInfo->LCDInfo & LCDNonExpanding )
+        {
+            tempax = pVBInfo->VGAHDE ;
+            tempbx = pVBInfo->VGAVDE ;
+        }
+
+        pVBInfo->HDE = tempax ;
+        pVBInfo->VDE = tempbx ;
+        return ;
+    }
+
+    if ( pVBInfo->VBInfo & ( SetCRT2ToTV ) )
+    {
+        tempbx = 4 ;
+        TVPtr = ( XGI_TVDataStruct * )XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+
+        pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX ;
+        pVBInfo->RVBHCFACT = TVPtr->RVBHCFACT ;
+        pVBInfo->VGAHT = TVPtr->VGAHT ;
+        pVBInfo->VGAVT = TVPtr->VGAVT ;
+        pVBInfo->HDE = TVPtr->TVHDE ;
+        pVBInfo->VDE = TVPtr->TVVDE ;
+        pVBInfo->RVBHRS = TVPtr->RVBHRS ;
+        pVBInfo->NewFlickerMode = TVPtr->FlickerMode ;
+
+        if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+        {
+            if ( resinfo == 0x08 )
+                pVBInfo->NewFlickerMode = 0x40 ;
+            else if ( resinfo == 0x09 )
+                pVBInfo->NewFlickerMode = 0x40 ;
+            else if ( resinfo == 0x12 )
+                pVBInfo->NewFlickerMode = 0x40 ;
+
+            if ( pVBInfo->VGAVDE == 350 )
+                pVBInfo->TVInfo |= TVSimuMode ;
+
+            tempax = ExtHiTVHT ;
+            tempbx = ExtHiTVVT ;
+
+            if ( pVBInfo->VBInfo & SetInSlaveMode )
+            {
+               if ( pVBInfo->TVInfo & TVSimuMode )
+               {
+                   tempax = StHiTVHT ;
+                   tempbx = StHiTVVT ;
+
+                   if ( !( modeflag & Charx8Dot ) )
+                   {
+                       tempax = StHiTextTVHT ;
+                       tempbx = StHiTextTVVT ;
+                   }
+               }
+            }
+        }
+        else if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+        {
+            if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+            {
+                tempax = YPbPrTV750pHT ;       /* Ext750pTVHT */
+                tempbx = YPbPrTV750pVT ;       /* Ext750pTVVT */
+            }
+
+            if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+            {
+                tempax = YPbPrTV525pHT ;       /* Ext525pTVHT */
+                tempbx = YPbPrTV525pVT ;       /* Ext525pTVVT */
+            }
+            else if ( pVBInfo->TVInfo & SetYPbPrMode525i )
+            {
+                tempax = YPbPrTV525iHT ;       /* Ext525iTVHT */
+                tempbx = YPbPrTV525iVT ;       /* Ext525iTVVT */
+                if ( pVBInfo->TVInfo & NTSC1024x768 )
+                    tempax = NTSC1024x768HT ;
+            }
+        }
+        else
+        {
+            tempax = PALHT ;
+            tempbx = PALVT ;
+            if ( !( pVBInfo->TVInfo & SetPALTV ) )
+            {
+                tempax = NTSCHT ;
+               tempbx = NTSCVT ;
+               if ( pVBInfo->TVInfo & NTSC1024x768 )
+                   tempax = NTSC1024x768HT ;
+            }
+        }
+
+        pVBInfo->HT = tempax ;
+        pVBInfo->VT = tempbx ;
+        return ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2VCLK */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT2VCLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR di_0 ,
+          di_1 ,
+          tempal ;
+
+    tempal = XGI_GetVCLKPtr( RefreshRateTableIndex , ModeNo , ModeIdIndex, pVBInfo ) ;
+    XGI_GetVCLKLen( tempal, &di_0 , &di_1, pVBInfo ) ;
+    XGI_GetLCDVCLKPtr( &di_0 , &di_1, pVBInfo ) ;
+
+    if ( pVBInfo->VBType & VB_XGI301 ) /* shampoo 0129 */
+    {                          /* 301 */
+        XGINew_SetReg1(pVBInfo->Part4Port , 0x0A , 0x10 ) ;
+        XGINew_SetReg1(pVBInfo->Part4Port , 0x0B , di_1 ) ;
+        XGINew_SetReg1(pVBInfo->Part4Port , 0x0A , di_0 ) ;
+    }
+    else
+    {                          /* 301b/302b/301lv/302lv */
+        XGINew_SetReg1( pVBInfo->Part4Port , 0x0A , di_0 ) ;
+        XGINew_SetReg1( pVBInfo->Part4Port , 0x0B , di_1 ) ;
+    }
+
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x00 , 0x12 ) ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+        XGINew_SetRegOR( pVBInfo->Part4Port , 0x12 , 0x28 ) ;
+    else
+        XGINew_SetRegOR( pVBInfo->Part4Port , 0x12 , 0x08 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GETLCDVCLKPtr */
+/* Input : */
+/* Output : al -> VCLK Index */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetLCDVCLKPtr( UCHAR* di_0 , UCHAR *di_1, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT index ;
+
+    if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+    {
+        if ( pVBInfo->IF_DEF_ScaleLCD == 1 )
+        {
+            if ( pVBInfo->LCDInfo & EnableScalingLCD )
+                return ;
+        }
+
+        /* index = XGI_GetLCDCapPtr(pVBInfo) ; */
+        index = XGI_GetLCDCapPtr1( pVBInfo) ;
+
+        if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+        {      /* LCDB */
+            *di_0 = pVBInfo->LCDCapList[ index ].LCUCHAR_VCLKData1 ;
+            *di_1 = pVBInfo->LCDCapList[ index ].LCUCHAR_VCLKData2 ;
+        }
+        else
+        {      /* LCDA */
+            *di_0 = pVBInfo->LCDCapList[ index ].LCDA_VCLKData1 ;
+            *di_1 = pVBInfo->LCDCapList[ index ].LCDA_VCLKData2 ;
+        }
+    }
+    return ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVCLKPtr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGI_GetVCLKPtr(USHORT RefreshRateTableIndex,USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+
+    USHORT index ,
+           modeflag ;
+#ifndef LINUX_XF86
+    USHORT tempbx ;
+#endif
+
+    UCHAR tempal ;
+    UCHAR *CHTVVCLKPtr = NULL ;
+
+    if ( ModeNo <= 0x13 )
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;      /* si+St_ResInfo */
+    else
+        modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;    /* si+Ext_ResInfo */
+
+
+    if ( ( pVBInfo->SetFlag & ProgrammingCRT2 ) && ( !( pVBInfo->LCDInfo & EnableScalingLCD ) ) )
+    {   /* {LCDA/LCDB} */
+        index = XGI_GetLCDCapPtr(pVBInfo) ;
+        tempal = pVBInfo->LCDCapList[ index ].LCD_VCLK ;
+
+        if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+            return tempal ;
+
+       /* {TV} */
+        if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV| VB_XGI302LV| VB_XGI301C ) )
+        {
+            if(pVBInfo->VBInfo&SetCRT2ToHiVisionTV)
+           {
+                tempal = HiTVVCLKDIV2;
+                if(!(pVBInfo->TVInfo & RPLLDIV2XO))
+                    tempal = HiTVVCLK;
+               if(pVBInfo->TVInfo & TVSimuMode)
+                {
+                    tempal = HiTVSimuVCLK;
+                    if(!(modeflag & Charx8Dot))
+                       tempal = HiTVTextVCLK;
+
+                 }
+                 return tempal;
+             }
+
+            if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+            {
+                tempal = YPbPr750pVCLK ;
+                return tempal ;
+            }
+
+            if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+            {
+                tempal = YPbPr525pVCLK ;
+                return tempal ;
+            }
+
+            tempal = NTSC1024VCLK ;
+
+            if ( !( pVBInfo->TVInfo & NTSC1024x768 ) )
+            {
+                tempal = TVVCLKDIV2 ;
+                if ( !( pVBInfo->TVInfo & RPLLDIV2XO ) )
+                    tempal = TVVCLK ;
+            }
+
+            if ( pVBInfo->VBInfo & SetCRT2ToTV )
+                return tempal ;
+        }
+        /*else
+        if((pVBInfo->IF_DEF_CH7017==1)&&(pVBInfo->VBType&VB_CH7017))
+        {
+            if(ModeNo<=0x13)
+                *tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+            else
+                *tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+            *tempal = *tempal & 0x1F;
+
+            tempbx = 0;
+            if(pVBInfo->TVInfo & SetPALTV)
+                tempbx = tempbx + 2;
+            if(pVBInfo->TVInfo & SetCHTVOverScan)
+                tempbx++;
+            tempbx = tempbx << 1;
+        }  */
+    }  /* {End of VB} */
+
+    if((pVBInfo->IF_DEF_CH7007==1)&&(pVBInfo->VBType&VB_CH7007)) /* [Billy] 07/05/08 CH7007 */
+    {
+       /* VideoDebugPrint((0, "XGI_GetVCLKPtr: pVBInfo->IF_DEF_CH7007==1\n")); */
+       if ( (pVBInfo->VBInfo & SetCRT2ToTV) )
+       {
+           if( ModeNo <= 0x13 )
+           {
+              tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+           }
+           else
+           {
+              tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+           }
+
+           tempal = tempal & 0x0F;
+           tempbx = 0;
+
+           if(pVBInfo->TVInfo & SetPALTV)
+           {
+              tempbx = tempbx + 2;
+           }
+           if(pVBInfo->TVInfo & SetCHTVOverScan)
+           {
+              tempbx++;
+           }
+           /** tempbx = tempbx << 1; CH7007 ? **/
+
+/*[Billy]07/05/29 CH7007*/
+           if ( pVBInfo->IF_DEF_CH7007 == 1 )
+           {
+             switch( tempbx )
+             {
+               case 0:
+                   CHTVVCLKPtr = XGI7007_CHTVVCLKUNTSC ;
+                   break ;
+               case 1:
+                   CHTVVCLKPtr = XGI7007_CHTVVCLKONTSC ;
+                   break ;
+               case 2:
+                   CHTVVCLKPtr = XGI7007_CHTVVCLKUPAL ;
+                   break ;
+               case 3:
+                   CHTVVCLKPtr = XGI7007_CHTVVCLKOPAL ;
+                   break ;
+               default:
+                   break ;
+
+             }
+           }
+           /*else
+           {
+            switch( tempbx )
+            {
+               case 0:
+                   CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC ;
+                   break ;
+               case 1:
+                   CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC ;
+                   break ;
+               case 2:
+                   CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL ;
+                   break ;
+               case 3:
+                   CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL ;
+                   break ;
+               default:
+                   break ;
+            }
+           }*/
+
+           tempal = CHTVVCLKPtr[ tempal ] ;
+           return tempal ;
+       }
+
+    }
+
+    tempal = ( UCHAR )XGINew_GetReg2( ( pVBInfo->P3ca + 0x02 ) ) ;
+    tempal = tempal >> 2 ;
+    tempal &= 0x03 ;
+
+    if ( ( pVBInfo->LCDInfo & EnableScalingLCD ) && ( modeflag & Charx8Dot ) )  /* for Dot8 Scaling LCD */
+        tempal = tempal ^ tempal ;                   /* ; set to VCLK25MHz always */
+
+    if ( ModeNo <= 0x13 )
+        return tempal ;
+
+    tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
+    return tempal ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVCLKLen */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInfo)
+{
+    if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 2007/05/16 */
+    {
+       /* VideoDebugPrint((0, "XGI_GetVCLKLen: pVBInfo->IF_DEF_CH7007==1\n")); */
+        *di_0 = ( UCHAR )XGI_CH7007VCLKData[ tempal ].SR2B ;
+        *di_1 = ( UCHAR )XGI_CH7007VCLKData[ tempal ].SR2C ;
+    }
+    else if ( pVBInfo->VBType & ( VB_XGI301 | VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        if ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( pVBInfo->SetFlag & ProgrammingCRT2 ) )
+        {
+            *di_0 = ( UCHAR )XGI_VBVCLKData[ tempal ].SR2B ;
+            *di_1 = XGI_VBVCLKData[ tempal ].SR2C ;
+        }
+    }
+    else
+    {
+        *di_0 = XGI_VCLKData[ tempal ].SR2B ;
+        *di_1 = XGI_VCLKData[ tempal ].SR2C ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2Offset */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT2Offset( USHORT ModeNo ,
+                                  USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT offset ;
+    UCHAR temp ;
+
+    if ( pVBInfo->VBInfo & SetInSlaveMode )
+    {
+        return ;
+    }
+
+    offset = XGI_GetOffset(  ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+    temp = ( UCHAR )( offset & 0xFF ) ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , temp ) ;
+    temp =( UCHAR)( ( offset & 0xFF00 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x09 , temp ) ;
+    temp =( UCHAR )( ( ( offset >> 3 ) & 0xFF ) + 1 ) ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetOffset */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetOffset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT temp ,
+           colordepth ,
+           modeinfo ,
+           index ,
+           infoflag ,
+           ColorDepth[] = { 0x01 , 0x02 , 0x04 } ;
+
+    modeinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeInfo ;
+    if ( ModeNo <= 0x14 )
+        infoflag = 0 ;
+    else
+        infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+
+
+    index = ( modeinfo >> 8 ) & 0xFF ;
+
+    temp = pVBInfo->ScreenOffset[ index ] ;
+
+    if ( infoflag & InterlaceMode )
+    {
+        temp = temp << 1 ;
+    }
+
+    colordepth = XGI_GetColorDepth( ModeNo , ModeIdIndex, pVBInfo ) ;
+
+    if ( ( ModeNo >= 0x7C ) && ( ModeNo <= 0x7E ) )
+    {
+        temp = ModeNo - 0x7C ;
+       colordepth = ColorDepth[ temp ] ;
+       temp = 0x6B ;
+       if ( infoflag & InterlaceMode )
+       {
+            temp = temp << 1 ;
+       }
+       return( temp * colordepth ) ;
+    }
+    else
+        return( temp * colordepth ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2FIFO */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT2FIFO( PVB_DEVICE_INFO pVBInfo)
+{
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x01 , 0x3B ) ;                       /* threshold high ,disable auto threshold */
+    XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x02 , ~( 0x3F ) , 0x04 ) ;       /* threshold low default 04h */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_PreSetGroup1 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_PreSetGroup1(USHORT ModeNo , USHORT ModeIdIndex ,PXGI_HW_DEVICE_INFO HwDeviceExtension,
+                       USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempcx = 0 ,
+           CRT1Index = 0 ,
+           resinfo = 0 ;
+
+    if ( ModeNo > 0x13 )
+    {
+        CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+        CRT1Index &= IndexMask ;
+        resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+    }
+
+    XGI_SetCRT2Offset( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+    XGI_SetCRT2FIFO(pVBInfo) ;
+    /* XGI_SetCRT2Sync(ModeNo,RefreshRateTableIndex); */
+
+    for( tempcx = 4 ; tempcx < 7 ; tempcx++ )
+    {
+        XGINew_SetReg1( pVBInfo->Part1Port , tempcx , 0x0 ) ;
+    }
+
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x50 , 0x00 ) ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x02 , 0x44 ) ;       /* temp 0206 */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGroup1 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGroup1( USHORT ModeNo , USHORT ModeIdIndex ,
+                            PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT temp = 0 ,
+           tempax = 0 ,
+           tempbx = 0 ,
+           tempcx = 0 ,
+           pushbx = 0 ,
+           CRT1Index = 0 ,
+           modeflag ,
+           resinfo = 0 ;
+
+    if ( ModeNo > 0x13 )
+    {
+        CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+        CRT1Index &= IndexMask ;
+        resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+    }
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+    }
+
+    /* bainy change table name */
+    if ( modeflag & HalfDCLK )
+    {
+        temp = ( pVBInfo->VGAHT / 2 - 1 ) & 0x0FF ;                    /* BTVGA2HT 0x08,0x09 */
+        XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , temp ) ;
+        temp = ( ( ( pVBInfo->VGAHT / 2 - 1 ) & 0xFF00 ) >> 8 ) << 4 ;
+        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x09 , ~0x0F0 , temp ) ;
+        temp = ( pVBInfo->VGAHDE / 2 + 16 ) & 0x0FF ;                  /* BTVGA2HDEE 0x0A,0x0C */
+        XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ;
+        tempcx = ( ( pVBInfo->VGAHT - pVBInfo->VGAHDE ) / 2 ) >> 2 ;
+        pushbx = pVBInfo->VGAHDE / 2 + 16 ;
+        tempcx = tempcx >> 1 ;
+        tempbx = pushbx + tempcx ;                                     /* bx BTVGA@HRS 0x0B,0x0C */
+        tempcx += tempbx ;
+
+       if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+       {
+            tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 4 ] ;
+            tempbx |= ( ( pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] & 0xC0 ) << 2 ) ;
+            tempbx = ( tempbx - 3 ) << 3 ;                             /* (VGAHRS-3)*8 */
+            tempcx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[ 5 ] ;
+            tempcx &= 0x1F ;
+            temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 15 ] ;
+            temp = ( temp & 0x04 ) << ( 5 - 2 ) ;                      /* VGAHRE D[5] */
+            tempcx = ( ( tempcx | temp ) - 3 ) << 3 ;                  /* (VGAHRE-3)*8 */
+        }
+
+        tempbx += 4 ;
+        tempcx += 4 ;
+
+        if ( tempcx > ( pVBInfo->VGAHT / 2 ) )
+            tempcx = pVBInfo->VGAHT / 2 ;
+
+        temp = tempbx & 0x00FF ;
+
+        XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ;
+    }
+    else
+    {
+        temp = ( pVBInfo->VGAHT - 1 ) & 0x0FF ;                                /* BTVGA2HT 0x08,0x09 */
+        XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , temp ) ;
+        temp = ( ( ( pVBInfo->VGAHT - 1 ) & 0xFF00 ) >> 8 ) << 4 ;
+        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x09 , ~0x0F0 , temp ) ;
+        temp = ( pVBInfo->VGAHDE + 16 ) & 0x0FF ;                              /* BTVGA2HDEE 0x0A,0x0C */
+        XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ;
+        tempcx = ( pVBInfo->VGAHT - pVBInfo->VGAHDE ) >> 2 ;           /* cx */
+        pushbx = pVBInfo->VGAHDE + 16 ;
+        tempcx = tempcx >> 1 ;
+        tempbx = pushbx + tempcx ;                                     /* bx BTVGA@HRS 0x0B,0x0C */
+        tempcx += tempbx ;
+
+        if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+        {
+            tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 3 ] ;
+            tempbx |= ( ( pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 5 ] & 0xC0 ) << 2 ) ;
+            tempbx = ( tempbx - 3 ) << 3 ;                             /* (VGAHRS-3)*8 */
+            tempcx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 4 ] ;
+            tempcx &= 0x1F ;
+            temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 6 ] ;
+            temp = ( temp & 0x04 ) << ( 5 - 2 ) ;                      /* VGAHRE D[5] */
+            tempcx = ( ( tempcx | temp ) - 3 ) << 3 ;                  /* (VGAHRE-3)*8 */
+            tempbx += 16 ;
+            tempcx += 16 ;
+        }
+
+        if ( tempcx > pVBInfo->VGAHT )
+            tempcx = pVBInfo->VGAHT ;
+
+        temp = tempbx & 0x00FF ;
+        XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ;
+    }
+
+    tempax = ( tempax & 0x00FF ) | ( tempbx & 0xFF00 ) ;
+    tempbx = pushbx ;
+    tempbx = ( tempbx & 0x00FF ) | ( ( tempbx & 0xFF00 ) << 4 ) ;
+    tempax |= ( tempbx & 0xFF00 ) ;
+    temp = ( tempax & 0xFF00 ) >> 8 ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , temp ) ;
+    temp = tempcx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x0D , temp ) ;
+    tempcx = ( pVBInfo->VGAVT - 1 ) ;
+    temp = tempcx & 0x00FF ;
+
+    if ( pVBInfo->IF_DEF_CH7005 == 1 )
+    {
+        if ( pVBInfo->VBInfo & 0x0C )
+        {
+            temp-- ;
+       }
+    }
+
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x0E , temp ) ;
+    tempbx = pVBInfo->VGAVDE - 1 ;
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x0F , temp ) ;
+    temp = ( ( tempbx & 0xFF00 ) << 3 ) >> 8 ;
+    temp |= ( ( tempcx & 0xFF00 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x12 , temp ) ;
+
+    tempax = pVBInfo->VGAVDE ;
+    tempbx = pVBInfo->VGAVDE ;
+    tempcx = pVBInfo->VGAVT ;
+    tempbx = ( pVBInfo->VGAVT + pVBInfo->VGAVDE ) >> 1 ;                               /* BTVGA2VRS 0x10,0x11 */
+    tempcx = ( ( pVBInfo->VGAVT - pVBInfo->VGAVDE ) >> 4 ) + tempbx + 1 ;              /* BTVGA2VRE 0x11 */
+
+    if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+    {
+        tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 10 ] ;
+        temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 9 ] ;
+
+        if ( temp & 0x04 )
+            tempbx |= 0x0100 ;
+
+        if ( temp & 0x080 )
+            tempbx |= 0x0200 ;
+
+        temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] ;
+
+        if ( temp & 0x08 )
+            tempbx |= 0x0400 ;
+
+        temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 11 ] ;
+        tempcx = ( tempcx & 0xFF00 ) | ( temp & 0x00FF ) ;
+    }
+
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x10 , temp ) ;
+    temp = ( ( tempbx & 0xFF00 ) >> 8 ) << 4 ;
+    temp = ( ( tempcx & 0x000F ) | ( temp ) ) ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x11 , temp ) ;
+    tempax = 0 ;
+
+    if ( modeflag & DoubleScanMode )
+        tempax |= 0x80 ;
+
+    if ( modeflag & HalfDCLK )
+        tempax |= 0x40 ;
+
+    XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2C , ~0x0C0 , tempax ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLockRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void  XGI_SetLockRegs( USHORT ModeNo , USHORT ModeIdIndex ,
+                                PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT push1 ,
+           push2 ,
+           tempax ,
+           tempbx = 0 ,
+           tempcx ,
+           temp ,
+           resinfo ,
+           modeflag ,
+           CRT1Index ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;  /* si+St_ResInfo */
+        resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
+        resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+        CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+        CRT1Index &= IndexMask;
+    }
+
+    if ( !( pVBInfo->VBInfo & SetInSlaveMode ) )
+    {
+        return ;
+    }
+
+    temp = 0xFF ;                                                      /* set MAX HT */
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , temp ) ;
+    /* if ( modeflag & Charx8Dot ) tempcx = 0x08 ; */
+    /* else */
+    tempcx=0x08;
+
+    if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        modeflag |= Charx8Dot ;
+
+    tempax = pVBInfo->VGAHDE ;                                         /* 0x04 Horizontal Display End */
+
+    if ( modeflag & HalfDCLK )
+        tempax = tempax >> 1 ;
+
+    tempax = ( tempax / tempcx ) - 1 ;
+    tempbx |= ( ( tempax & 0x00FF ) << 8 ) ;
+    temp = tempax & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x04 , temp ) ;
+
+    temp = ( tempbx & 0xFF00 ) >> 8 ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToTV )
+    {
+        if ( !( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) )
+            temp += 2 ;
+
+        if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+        {
+            if ( pVBInfo->VBType & VB_XGI301LV )
+            {
+                if ( pVBInfo->VBExtInfo == VB_YPbPr1080i )
+                {
+                    if ( resinfo == 7 )
+                        temp -= 2 ;
+                }
+            }
+            else
+                if ( resinfo == 7 )
+                    temp -= 2 ;
+        }
+    }
+
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x05 , temp ) ;                       /* 0x05 Horizontal Display Start */
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x06 , 0x03 ) ;                       /* 0x06 Horizontal Blank end */
+
+    if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
+    {                                                                  /* 030226 bainy */
+        if ( pVBInfo->VBInfo & SetCRT2ToTV )
+            tempax = pVBInfo->VGAHT ;
+        else
+            tempax = XGI_GetVGAHT2( pVBInfo) ;
+    }
+
+    if ( tempax >= pVBInfo->VGAHT )
+    {
+        tempax = pVBInfo->VGAHT ;
+    }
+
+    if ( modeflag & HalfDCLK )
+    {
+        tempax = tempax >> 1 ;
+    }
+
+    tempax = ( tempax / tempcx ) - 5 ;
+    tempcx = tempax ;                          /* 20030401 0x07 horizontal Retrace Start */
+    if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+    {
+        temp = ( tempbx & 0x00FF ) - 1 ;
+        if ( !( modeflag & HalfDCLK ) )
+        {
+            temp -= 6 ;
+            if ( pVBInfo->TVInfo & TVSimuMode )
+            {
+                temp -= 4 ;
+                if ( ModeNo > 0x13 )
+                    temp -= 10 ;
+            }
+        }
+    }
+    else
+    {
+        /* tempcx = tempbx & 0x00FF ; */
+        tempbx = ( tempbx & 0xFF00 ) >> 8 ;
+        tempcx = ( tempcx + tempbx ) >> 1 ;
+        temp = ( tempcx & 0x00FF ) + 2 ;
+
+        if ( pVBInfo->VBInfo & SetCRT2ToTV )
+        {
+            temp -= 1 ;
+            if ( !( modeflag & HalfDCLK ) )
+            {
+                if ( ( modeflag & Charx8Dot ) )
+                {
+                    temp += 4 ;
+                    if ( pVBInfo->VGAHDE >= 800 )
+                    {
+                        temp -= 6 ;
+                    }
+                }
+            }
+        }
+        else
+        {
+            if ( !( modeflag & HalfDCLK ) )
+            {
+                temp -= 4 ;
+                if ( pVBInfo->LCDResInfo != Panel1280x960 )
+                {
+                    if( pVBInfo->VGAHDE >= 800 )
+                    {
+                        temp -= 7 ;
+                        if ( pVBInfo->ModeType == ModeEGA )
+                        {
+                            if ( pVBInfo->VGAVDE == 1024 )
+                            {
+                                temp += 15 ;
+                                if ( pVBInfo->LCDResInfo != Panel1280x1024 )
+                                {
+                                    temp += 7 ;
+                                }
+                            }
+                        }
+
+                        if ( pVBInfo->VGAHDE >= 1280 )
+                        {
+                            if ( pVBInfo->LCDResInfo != Panel1280x960 )
+                            {
+                                if ( pVBInfo->LCDInfo & LCDNonExpanding )
+                                {
+                                    temp += 28 ;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , temp ) ;               /* 0x07 Horizontal Retrace Start */
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0 ) ;          /* 0x08 Horizontal Retrace End */
+
+    if ( pVBInfo->VBInfo & SetCRT2ToTV )
+    {
+        if ( pVBInfo->TVInfo & TVSimuMode )
+        {
+            if ( ( ModeNo == 0x06 ) || ( ModeNo == 0x10 ) || ( ModeNo == 0x11 ) || ( ModeNo == 0x13 ) || ( ModeNo == 0x0F ) )
+            {
+                XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x5b ) ;
+                XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x03 ) ;
+            }
+
+            if ( ( ModeNo == 0x00 ) || ( ModeNo == 0x01 ) )
+            {
+                if ( pVBInfo->TVInfo & SetNTSCTV )
+                {
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2A ) ;
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x61 ) ;
+                }
+                else
+                {
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2A ) ;
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x41 ) ;
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , 0xF0 ) ;
+                }
+            }
+
+            if ( ( ModeNo == 0x02 ) || ( ModeNo == 0x03 ) || ( ModeNo == 0x07 ) )
+            {
+                if ( pVBInfo->TVInfo & SetNTSCTV )
+                {
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x54 ) ;
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x00 ) ;
+                }
+                else
+                {
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x55 ) ;
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x00 ) ;
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , 0xF0 ) ;
+                }
+            }
+
+            if ( ( ModeNo == 0x04 ) || ( ModeNo == 0x05 ) || ( ModeNo == 0x0D ) || ( ModeNo == 0x50 ) )
+            {
+                if ( pVBInfo->TVInfo & SetNTSCTV )
+                {
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x30 ) ;
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x03 ) ;
+                }
+                else
+                {
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2f ) ;
+                    XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x02 ) ;
+                }
+            }
+        }
+    }
+
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x18 , 0x03 ) ;                               /* 0x18 SR0B */
+    XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0xF0 , 0x00 ) ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x09 , 0xFF ) ;                               /* 0x09 Set Max VT */
+
+    tempbx = pVBInfo->VGAVT ;
+    push1 = tempbx ;
+    tempcx = 0x121 ;
+    tempbx = pVBInfo->VGAVDE ;                                                 /* 0x0E Virtical Display End */
+
+    if ( tempbx == 357 )
+        tempbx = 350 ;
+    if ( tempbx == 360 )
+        tempbx =350 ;
+    if ( tempbx == 375 )
+        tempbx = 350 ;
+    if ( tempbx == 405 )
+        tempbx = 400 ;
+    if ( tempbx == 525 )
+        tempbx = 480 ;
+
+    push2 = tempbx ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+    {
+        if ( pVBInfo->LCDResInfo == Panel1024x768 )
+        {
+            if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+            {
+                if ( tempbx == 350 )
+                    tempbx += 5 ;
+               if ( tempbx == 480 )
+                   tempbx += 5 ;
+            }
+        }
+    }
+    tempbx-- ;
+    temp = tempbx & 0x00FF ;
+    tempbx-- ;
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x10 ,temp ) ;                                /* 0x10 vertical Blank Start */
+    tempbx = push2 ;
+    tempbx-- ;
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x0E , temp ) ;
+
+    if ( tempbx & 0x0100 )
+    {
+        tempcx |= 0x0002 ;
+    }
+
+    tempax = 0x000B ;
+
+    if ( modeflag & DoubleScanMode )
+    {
+        tempax |= 0x08000 ;
+    }
+
+    if ( tempbx & 0x0200 )
+    {
+        tempcx |= 0x0040 ;
+    }
+
+    temp = ( tempax & 0xFF00 ) >> 8 ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ;
+
+    if ( tempbx & 0x0400 )
+    {
+        tempcx |= 0x0600 ;
+    }
+
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x11 , 0x00 ) ;                               /* 0x11 Vertival Blank End */
+
+    tempax = push1 ;
+    tempax -= tempbx ;                                                         /* 0x0C Vertical Retrace Start */
+    tempax = tempax >> 2 ;
+    push1 = tempax ;                                                           /* push ax */
+
+    if ( resinfo != 0x09 )
+    {
+        tempax = tempax << 1 ;
+        tempbx += tempax ;
+    }
+
+    if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+    {
+        if ( pVBInfo->VBType & VB_XGI301LV )
+        {
+            if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
+                tempbx -= 10 ;
+            else
+            {
+                if ( pVBInfo->TVInfo & TVSimuMode )
+                {
+                    if ( pVBInfo->TVInfo & SetPALTV )
+                    {
+                        if ( pVBInfo->VBType & VB_XGI301LV )
+                        {
+                            if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
+                                tempbx += 40 ;
+                        }
+                        else
+                            tempbx += 40 ;
+                    }
+                }
+            }
+        }
+        else
+            tempbx -= 10 ;
+    }
+    else
+    {
+        if ( pVBInfo->TVInfo & TVSimuMode )
+        {
+            if ( pVBInfo->TVInfo & SetPALTV )
+            {
+                if ( pVBInfo->VBType & VB_XGI301LV )
+                {
+                    if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
+                        tempbx += 40 ;
+                }
+                else
+                    tempbx += 40 ;
+            }
+        }
+    }
+    tempax = push1 ;
+    tempax = tempax >> 2 ;
+    tempax++ ;
+    tempax += tempbx ;
+    push1 = tempax ;                                           /* push ax */
+
+    if ( ( pVBInfo->TVInfo & SetPALTV ) )
+    {
+        if ( tempbx <= 513 )
+        {
+            if ( tempax >= 513 )
+            {
+                tempbx = 513 ;
+            }
+        }
+    }
+
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , temp ) ;
+    tempbx-- ;
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x10 , temp ) ;
+
+    if ( tempbx & 0x0100 )
+    {
+        tempcx |= 0x0008 ;
+    }
+
+    if ( tempbx & 0x0200 )
+    {
+        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x0B , 0x0FF , 0x20 ) ;
+    }
+
+    tempbx++ ;
+
+    if ( tempbx & 0x0100 )
+    {
+        tempcx |= 0x0004 ;
+    }
+
+    if ( tempbx & 0x0200 )
+    {
+        tempcx |= 0x0080 ;
+    }
+
+    if ( tempbx & 0x0400 )
+    {
+        tempcx |= 0x0C00 ;
+    }
+
+    tempbx = push1 ;                                           /* pop ax */
+    temp = tempbx & 0x00FF ;
+    temp &= 0x0F ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x0D , temp ) ;               /* 0x0D vertical Retrace End */
+
+    if ( tempbx & 0x0010 )
+    {
+        tempcx |= 0x2000 ;
+    }
+
+    temp = tempcx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ;               /* 0x0A CR07 */
+    temp = ( tempcx & 0x0FF00 ) >> 8 ;
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x17 , temp ) ;               /* 0x17 SR0A */
+    tempax = modeflag ;
+    temp = ( tempax & 0xFF00 ) >> 8 ;
+
+    temp = ( temp >> 1 ) & 0x09 ;
+
+    if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        temp |= 0x01 ;
+
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x16 , temp ) ;                       /* 0x16 SR01 */
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x0F , 0 ) ;                  /* 0x0F CR14 */
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x12 , 0 ) ;                  /* 0x12 CR17 */
+
+    if ( pVBInfo->LCDInfo & LCDRGB18Bit )
+        temp = 0x80 ;
+    else
+        temp = 0x00 ;
+
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x1A , temp ) ;                       /* 0x1A SR0E */
+
+    return ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGroup2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGroup2( USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
+                    PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT i ,
+           j ,
+           tempax ,
+           tempbx ,
+           tempcx ,
+           temp ,
+           push1 ,
+           push2 ,
+           modeflag ,
+           resinfo ,
+           crt2crtc ;
+    UCHAR *TimingPoint ;
+
+    ULONG longtemp ,
+          tempeax ,
+          tempebx ,
+          temp2 ,
+          tempecx ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;          /* si+St_ResInfo */
+        resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
+        crt2crtc = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;         /* si+Ext_ResInfo */
+        resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+        crt2crtc = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
+    }
+
+    tempax = 0 ;
+
+    if ( !( pVBInfo->VBInfo & SetCRT2ToAVIDEO ) )
+        tempax |= 0x0800 ;
+
+    if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) )
+        tempax |= 0x0400 ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToSCART )
+        tempax |= 0x0200 ;
+
+    if ( !( pVBInfo->TVInfo & SetPALTV ) )
+        tempax |= 0x1000 ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+        tempax |= 0x0100 ;
+
+    if ( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
+        tempax &= 0xfe00 ;
+
+    tempax = ( tempax & 0xff00 ) >> 8 ;
+
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x0 , tempax ) ;
+    TimingPoint = pVBInfo->NTSCTiming ;
+
+    if ( pVBInfo->TVInfo & SetPALTV )
+    {
+        TimingPoint = pVBInfo->PALTiming ;
+    }
+
+    if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+    {
+        TimingPoint = pVBInfo->HiTVExtTiming ;
+
+        if ( pVBInfo->VBInfo & SetInSlaveMode )
+            TimingPoint = pVBInfo->HiTVSt2Timing ;
+
+        if ( pVBInfo->SetFlag & TVSimuMode )
+            TimingPoint = pVBInfo->HiTVSt1Timing ;
+
+        if ( !(modeflag & Charx8Dot) )
+            TimingPoint = pVBInfo->HiTVTextTiming ;
+    }
+
+    if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+    {
+        if ( pVBInfo->TVInfo & SetYPbPrMode525i )
+            TimingPoint = pVBInfo->YPbPr525iTiming ;
+
+        if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+           TimingPoint = pVBInfo->YPbPr525pTiming ;
+
+        if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+           TimingPoint = pVBInfo->YPbPr750pTiming ;
+    }
+
+    for( i = 0x01 , j = 0 ; i <= 0x2D ; i++ , j++ )
+    {
+        XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ;
+    }
+
+    for( i = 0x39 ; i <= 0x45 ; i++ , j++ )
+    {
+        XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ;  /* di->temp2[j] */
+    }
+
+    if ( pVBInfo->VBInfo & SetCRT2ToTV )
+    {
+        XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x3A , 0x1F , 0x00 ) ;
+    }
+
+    temp = pVBInfo->NewFlickerMode ;
+    temp &= 0x80 ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0xFF , temp ) ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+        tempax = 950 ;
+
+    if ( pVBInfo->TVInfo & SetPALTV )
+        tempax = 520 ;
+    else
+        tempax = 440 ;
+
+    if ( pVBInfo->VDE <= tempax )
+    {
+        tempax -= pVBInfo->VDE ;
+        tempax = tempax >> 2 ;
+        tempax = ( tempax & 0x00FF ) | ( ( tempax & 0x00FF ) << 8 ) ;
+        push1 = tempax ;
+        temp = ( tempax & 0xFF00 ) >> 8 ;
+        temp += ( USHORT )TimingPoint[ 0 ] ;
+
+        if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        {
+            if ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr ) )
+            {
+                tempcx=pVBInfo->VGAHDE;
+                if ( tempcx >= 1024 )
+                {
+                    temp = 0x17 ;              /* NTSC */
+                    if ( pVBInfo->TVInfo & SetPALTV )
+                        temp = 0x19 ;          /* PAL */
+                }
+            }
+        }
+
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x01 , temp ) ;
+        tempax = push1 ;
+        temp = ( tempax & 0xFF00 ) >> 8 ;
+        temp += TimingPoint[ 1 ] ;
+
+        if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        {
+            if ( ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr ) ) )
+            {
+                tempcx = pVBInfo->VGAHDE ;
+                if ( tempcx >= 1024 )
+                {
+                    temp = 0x1D ;              /* NTSC */
+                    if ( pVBInfo->TVInfo & SetPALTV )
+                        temp = 0x52 ;          /* PAL */
+                }
+            }
+        }
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x02 , temp ) ;
+    }
+
+    /* 301b */
+    tempcx = pVBInfo->HT ;
+
+    if ( XGI_IsLCDDualLink( pVBInfo ) )
+        tempcx = tempcx >> 1 ;
+
+    tempcx -= 2 ;
+    temp = tempcx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x1B , temp ) ;
+
+    temp = ( tempcx & 0xFF00 ) >> 8 ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1D , ~0x0F , temp ) ;
+
+    tempcx = pVBInfo->HT >> 1 ;
+    push1 = tempcx ;                           /* push cx */
+    tempcx += 7 ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+    {
+        tempcx -= 4 ;
+    }
+
+    temp = tempcx & 0x00FF ;
+    temp = temp << 4 ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x22 , 0x0F , temp ) ;
+
+    tempbx = TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ;
+    tempbx += tempcx ;
+    push2 = tempbx ;
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x24 , temp ) ;
+    temp = ( tempbx & 0xFF00 ) >> 8 ;
+    temp = temp << 4 ;
+    XGINew_SetRegANDOR(pVBInfo->Part2Port,0x25,0x0F,temp);
+
+    tempbx=push2;
+    tempbx=tempbx+8;
+    if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+    {
+        tempbx=tempbx-4;
+        tempcx=tempbx;
+    }
+
+    temp = ( tempbx & 0x00FF ) << 4 ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x29 , 0x0F , temp ) ;
+
+    j += 2 ;
+    tempcx += ( TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ) ;
+    temp = tempcx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x27 , temp ) ;
+    temp = ( ( tempcx & 0xFF00 ) >> 8 ) << 4 ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x28 , 0x0F , temp ) ;
+
+    tempcx += 8 ;
+    if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+    {
+        tempcx -= 4 ;
+    }
+
+    temp = tempcx & 0xFF ;
+    temp = temp << 4 ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2A , 0x0F , temp ) ;
+
+    tempcx = push1 ;                                   /* pop cx */
+    j += 2 ;
+    temp = TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ;
+    tempcx -= temp ;
+    temp = tempcx & 0x00FF ;
+    temp = temp << 4 ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2D , 0x0F ,temp ) ;
+
+    tempcx -= 11 ;
+
+    if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) )
+    {
+        tempax = XGI_GetVGAHT2( pVBInfo) ;
+        tempcx = tempax - 1 ;
+    }
+    temp = tempcx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x2E , temp ) ;
+
+    tempbx = pVBInfo->VDE ;
+
+    if ( pVBInfo->VGAVDE == 360 )
+        tempbx = 746 ;
+    if ( pVBInfo->VGAVDE == 375 )
+        tempbx = 746 ;
+    if ( pVBInfo->VGAVDE == 405 )
+        tempbx = 853 ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToTV )
+    {
+        if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        {
+            if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) )
+                tempbx = tempbx >> 1 ;
+        }
+        else
+            tempbx = tempbx >> 1 ;
+    }
+
+    tempbx -= 2 ;
+    temp = tempbx & 0x00FF ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+    {
+        if ( pVBInfo->VBType & VB_XGI301LV )
+        {
+            if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
+            {
+                if ( pVBInfo->VBInfo & SetInSlaveMode )
+                {
+                    if ( ModeNo == 0x2f )
+                        temp += 1 ;
+                }
+            }
+        }
+        else
+        {
+            if ( pVBInfo->VBInfo & SetInSlaveMode )
+            {
+                if ( ModeNo == 0x2f )
+                    temp += 1 ;
+            }
+        }
+    }
+
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x2F , temp ) ;
+
+    temp = ( tempcx & 0xFF00 ) >> 8 ;
+    temp |= ( ( tempbx & 0xFF00 ) >> 8 ) << 6 ;
+
+    if ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) )
+    {
+        if ( pVBInfo->VBType & VB_XGI301LV )
+        {
+            if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
+            {
+                temp |= 0x10 ;
+
+                if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) )
+                    temp |= 0x20 ;
+            }
+        }
+        else
+        {
+            temp |= 0x10 ;
+            if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) )
+                temp |= 0x20 ;
+        }
+    }
+
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x30 , temp ) ;
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )      /* TV gatingno */
+    {
+        tempbx = pVBInfo->VDE ;
+        tempcx = tempbx - 2 ;
+
+        if ( pVBInfo->VBInfo & SetCRT2ToTV )
+        {
+            if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) )
+                tempbx = tempbx >> 1 ;
+        }
+
+        if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
+        {
+            temp=0;
+            if( tempcx & 0x0400 )
+                temp |= 0x20 ;
+
+            if ( tempbx & 0x0400 )
+                temp |= 0x40 ;
+
+            XGINew_SetReg1( pVBInfo->Part4Port , 0x10 , temp ) ;
+        }
+
+        temp = ( ( ( tempbx - 3 ) & 0x0300 ) >> 8 ) << 5 ;
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x46 , temp ) ;
+        temp = ( tempbx - 3 ) & 0x00FF ;
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x47 , temp ) ;
+    }
+
+    tempbx = tempbx & 0x00FF ;
+
+    if ( !( modeflag & HalfDCLK ) )
+    {
+        tempcx = pVBInfo->VGAHDE ;
+        if ( tempcx >= pVBInfo->HDE )
+        {
+            tempbx |= 0x2000 ;
+            tempax &= 0x00FF ;
+        }
+    }
+
+    tempcx = 0x0101 ;
+
+    if( pVBInfo->VBInfo & SetCRT2ToTV ) { /*301b*/
+        if(pVBInfo->VGAHDE>=1024)
+        {
+           tempcx=0x1920;
+            if(pVBInfo->VGAHDE>=1280)
+            {
+               tempcx=0x1420;
+               tempbx=tempbx&0xDFFF;
+            }
+        }
+    }
+
+    if ( !( tempbx & 0x2000 ) )
+    {
+        if ( modeflag & HalfDCLK )
+        {
+            tempcx = ( tempcx & 0xFF00 ) | ( ( tempcx & 0x00FF ) << 1 ) ;
+       }
+
+        push1 = tempbx ;
+        tempeax = pVBInfo->VGAHDE ;
+        tempebx = ( tempcx & 0xFF00 ) >> 8 ;
+        longtemp = tempeax * tempebx ;
+        tempecx = tempcx & 0x00FF ;
+        longtemp = longtemp / tempecx ;
+
+       /* 301b */
+        tempecx = 8 * 1024 ;
+
+        if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        {
+            tempecx = tempecx * 8 ;
+        }
+
+        longtemp = longtemp * tempecx ;
+        tempecx = pVBInfo->HDE ;
+        temp2 = longtemp % tempecx ;
+        tempeax = longtemp / tempecx ;
+        if ( temp2 != 0 )
+        {
+            tempeax += 1 ;
+        }
+
+        tempax = ( USHORT )tempeax ;
+
+       /* 301b */
+        if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        {
+            tempcx = ( ( tempax & 0xFF00 ) >> 5 ) >> 8 ;
+        }
+        /* end 301b */
+
+        tempbx = push1 ;
+        tempbx =( USHORT )( ( ( tempeax & 0x0000FF00 ) & 0x1F00 ) | ( tempbx & 0x00FF ) ) ;
+        tempax =( USHORT )( ( ( tempeax & 0x000000FF ) << 8 ) | ( tempax & 0x00FF ) ) ;
+        temp = ( tempax & 0xFF00 ) >> 8 ;
+    }
+    else
+    {
+        temp = ( tempax & 0x00FF ) >> 8 ;
+    }
+
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x44 , temp ) ;
+    temp = ( tempbx & 0xFF00 ) >> 8 ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x45 , ~0x03F , temp ) ;
+    temp = tempcx & 0x00FF ;
+
+    if ( tempbx & 0x2000 )
+        temp = 0 ;
+
+    if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
+        temp |= 0x18 ;
+
+    XGINew_SetRegANDOR(pVBInfo->Part2Port,0x46,~0x1F,temp);
+    if ( pVBInfo->TVInfo & SetPALTV )
+    {
+        tempbx = 0x0382 ;
+        tempcx = 0x007e ;
+    }
+    else
+    {
+        tempbx = 0x0369 ;
+        tempcx = 0x0061 ;
+    }
+
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x4b , temp ) ;
+    temp = tempcx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x4c , temp ) ;
+
+    temp = ( ( tempcx & 0xFF00 ) >> 8 ) & 0x03 ;
+    temp = temp << 2 ;
+    temp |= ( ( tempbx & 0xFF00 ) >> 8 ) & 0x03 ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+    {
+        temp |= 0x10 ;
+
+        if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+            temp |= 0x20 ;
+
+        if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+            temp |= 0x60 ;
+    }
+
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x4d , temp ) ;
+    temp=XGINew_GetReg1( pVBInfo->Part2Port , 0x43 ) ;         /* 301b change */
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x43 , ( USHORT )( temp - 3 ) ) ;
+
+    if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) )
+    {
+        if ( pVBInfo->TVInfo & NTSC1024x768 )
+        {
+            TimingPoint = XGI_NTSC1024AdjTime ;
+            for( i = 0x1c , j = 0 ; i <= 0x30 ; i++ , j++ )
+            {
+                XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ;
+            }
+            XGINew_SetReg1( pVBInfo->Part2Port , 0x43 , 0x72 ) ;
+        }
+    }
+
+    /* [ycchen] 01/14/03 Modify for 301C PALM Support */
+    if ( pVBInfo->VBType & VB_XGI301C )
+    {
+        if ( pVBInfo->TVInfo & SetPALMTV )
+           XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x08 , 0x08 ) ;    /* PALM Mode */
+    }
+
+    if ( pVBInfo->TVInfo & SetPALMTV )
+    {
+        tempax = ( UCHAR )XGINew_GetReg1( pVBInfo->Part2Port , 0x01 ) ;
+        tempax-- ;
+        XGINew_SetRegAND( pVBInfo->Part2Port , 0x01 , tempax ) ;
+
+        /* if ( !( pVBInfo->VBType & VB_XGI301C ) ) */
+        XGINew_SetRegAND( pVBInfo->Part2Port , 0x00 , 0xEF ) ;
+    }
+
+    if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+    {
+        if ( !( pVBInfo->VBInfo & SetInSlaveMode ) )
+        {
+            XGINew_SetReg1( pVBInfo->Part2Port , 0x0B , 0x00 ) ;
+        }
+    }
+
+    if ( pVBInfo->VBInfo & SetCRT2ToTV )
+    {
+        return ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLCDRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void  XGI_SetLCDRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT push1 ,
+           push2 ,
+           pushbx ,
+           tempax ,
+           tempbx ,
+           tempcx ,
+           temp ,
+           tempah ,
+           tempbh ,
+           tempch ,
+           resinfo ,
+           modeflag ,
+           CRT1Index ;
+
+    XGI_LCDDesStruct *LCDBDesPtr = NULL ;
+
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;  /* si+St_ResInfo */
+        resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
+        resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+        CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+        CRT1Index &= IndexMask ;
+    }
+
+    if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
+    {
+        return ;
+    }
+
+    tempbx = pVBInfo->HDE ;                    /* RHACTE=HDE-1 */
+
+    if ( XGI_IsLCDDualLink( pVBInfo ) )
+        tempbx = tempbx >> 1 ;
+
+    tempbx -= 1 ;
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x2C , temp ) ;
+    temp = ( tempbx & 0xFF00 ) >> 8 ;
+    temp = temp << 4 ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2B , 0x0F , temp ) ;
+    temp = 0x01 ;
+
+    if ( pVBInfo->LCDResInfo == Panel1280x1024 )
+    {
+        if ( pVBInfo->ModeType == ModeEGA )
+        {
+            if ( pVBInfo->VGAHDE >= 1024 )
+            {
+                temp = 0x02 ;
+                if ( pVBInfo->LCDInfo & LCDVESATiming )
+                    temp = 0x01 ;
+            }
+        }
+    }
+
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x0B , temp ) ;
+    tempbx = pVBInfo->VDE ;                    /* RTVACTEO=(VDE-1)&0xFF */
+    push1 = tempbx ;
+    tempbx-- ;
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x03 , temp ) ;
+    temp = ( ( tempbx & 0xFF00 ) >> 8 ) & 0x07 ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0C , ~0x07 , temp ) ;
+
+    tempcx = pVBInfo->VT - 1 ;
+    push2 = tempcx + 1 ;
+    temp = tempcx & 0x00FF ;                   /* RVTVT=VT-1 */
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x19 , temp ) ;
+    temp = ( tempcx & 0xFF00 ) >> 8 ;
+    temp = temp << 5 ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x1A , temp ) ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x09 , 0xF0 , 0x00 ) ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0xF0 , 0x00 ) ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x17 , 0xFB , 0x00 ) ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x18 , 0xDF , 0x00 ) ;
+
+    /* Customized LCDB Des no add */
+    tempbx = 5 ;
+    LCDBDesPtr = ( XGI_LCDDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+    tempah = pVBInfo->LCDResInfo ;
+    tempah &= PanelResInfo ;
+
+    if ( ( tempah == Panel1024x768 ) || ( tempah == Panel1024x768x75 ) )
+    {
+        tempbx = 1024 ;
+        tempcx = 768 ;
+    }
+    else if ( ( tempah == Panel1280x1024 ) || ( tempah == Panel1280x1024x75 ) )
+    {
+        tempbx = 1280 ;
+        tempcx = 1024 ;
+    }
+    else if ( tempah == Panel1400x1050 )
+    {
+        tempbx = 1400 ;
+        tempcx = 1050 ;
+    }
+    else
+    {
+        tempbx = 1600 ;
+        tempcx = 1200 ;
+    }
+
+    if ( pVBInfo->LCDInfo & EnableScalingLCD )
+    {
+        tempbx = pVBInfo->HDE ;
+        tempcx = pVBInfo->VDE ;
+    }
+
+    pushbx = tempbx ;
+    tempax = pVBInfo->VT ;
+    pVBInfo->LCDHDES = LCDBDesPtr->LCDHDES ;
+    pVBInfo->LCDHRS = LCDBDesPtr->LCDHRS ;
+    pVBInfo->LCDVDES = LCDBDesPtr->LCDVDES ;
+    pVBInfo->LCDVRS = LCDBDesPtr->LCDVRS ;
+    tempbx = pVBInfo->LCDVDES ;
+    tempcx += tempbx ;
+
+    if ( tempcx >= tempax )
+        tempcx -= tempax ;     /* lcdvdes */
+
+    temp = tempbx & 0x00FF ;   /* RVEQ1EQ=lcdvdes */
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x05 , temp ) ;
+    temp = tempcx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x06 , temp ) ;
+    tempch = ( ( tempcx & 0xFF00 ) >> 8 ) & 0x07 ;
+    tempbh = ( ( tempbx & 0xFF00 ) >> 8 ) & 0x07 ;
+    tempah = tempch ;
+    tempah = tempah << 3 ;
+    tempah |= tempbh ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x02 , tempah ) ;
+
+    /* getlcdsync() */
+    XGI_GetLCDSync( &tempax , &tempbx,pVBInfo ) ;
+    tempcx = tempbx ;
+    tempax = pVBInfo->VT ;
+    tempbx = pVBInfo->LCDVRS ;
+
+    /* if ( SetLCD_Info & EnableScalingLCD ) */
+    tempcx += tempbx ;
+    if ( tempcx >= tempax )
+        tempcx -= tempax ;
+
+    temp = tempbx & 0x00FF ;   /* RTVACTEE=lcdvrs */
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x04 , temp ) ;
+    temp = ( tempbx & 0xFF00 ) >> 8 ;
+    temp = temp << 4 ;
+    temp |= ( tempcx & 0x000F ) ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x01 , temp ) ;
+    tempcx = pushbx ;
+    tempax = pVBInfo->HT ;
+    tempbx = pVBInfo->LCDHDES ;
+    tempbx &= 0x0FFF ;
+
+    if ( XGI_IsLCDDualLink(  pVBInfo ) )
+    {
+        tempax = tempax >> 1 ;
+        tempbx = tempbx >> 1 ;
+        tempcx = tempcx >> 1 ;
+    }
+
+    if ( pVBInfo->VBType & VB_XGI302LV )
+        tempbx += 1 ;
+
+    if ( pVBInfo->VBType & VB_XGI301C )  /* tap4 */
+        tempbx += 1 ;
+
+    tempcx += tempbx ;
+
+    if ( tempcx >= tempax )
+        tempcx -= tempax ;
+
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x1F , temp ) ;       /* RHBLKE=lcdhdes */
+    temp = ( ( tempbx & 0xFF00 ) >> 8 ) << 4 ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x20 , temp ) ;
+    temp = tempcx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x23 , temp ) ;       /* RHEQPLE=lcdhdee */
+    temp = ( tempcx & 0xFF00 ) >> 8 ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x25 , temp ) ;
+
+    /* getlcdsync() */
+    XGI_GetLCDSync( &tempax , &tempbx ,pVBInfo) ;
+    tempcx = tempax ;
+    tempax = pVBInfo->HT ;
+    tempbx = pVBInfo->LCDHRS ;
+    /* if ( SetLCD_Info & EnableScalingLCD) */
+    if ( XGI_IsLCDDualLink( pVBInfo) )
+    {
+        tempax = tempax >> 1 ;
+        tempbx = tempbx >> 1 ;
+        tempcx = tempcx >> 1 ;
+    }
+
+    if ( pVBInfo->VBType & VB_XGI302LV )
+        tempbx += 1 ;
+
+    tempcx += tempbx ;
+
+    if ( tempcx >= tempax )
+        tempcx -= tempax ;
+
+    temp = tempbx & 0x00FF ;   /* RHBURSTS=lcdhrs */
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x1C , temp ) ;
+
+    temp = ( tempbx & 0xFF00 ) >> 8 ;
+    temp = temp << 4 ;
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1D , ~0x0F0 , temp ) ;
+    temp = tempcx & 0x00FF ;   /* RHSYEXP2S=lcdhre */
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x21 , temp ) ;
+
+    if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+    {
+        if ( pVBInfo->VGAVDE == 525 )
+        {
+            if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+            {
+                temp = 0xC6 ;
+            }
+            else
+                temp = 0xC4 ;
+
+            XGINew_SetReg1( pVBInfo->Part2Port , 0x2f , temp ) ;
+            XGINew_SetReg1( pVBInfo->Part2Port , 0x30 , 0xB3 ) ;
+        }
+
+        if ( pVBInfo->VGAVDE == 420 )
+        {
+            if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+            {
+                temp = 0x4F ;
+            }
+            else
+                temp = 0x4E ;
+            XGINew_SetReg1( pVBInfo->Part2Port , 0x2f , temp ) ;
+        }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetTap4Ptr */
+/* Input : */
+/* Output : di -> Tap4 Reg. Setting Pointer */
+/* Description : */
+/* --------------------------------------------------------------------- */
+XGI301C_Tap4TimingStruct* XGI_GetTap4Ptr(USHORT tempcx, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempax ,
+           tempbx ,
+           i ;
+
+    XGI301C_Tap4TimingStruct *Tap4TimingPtr ;
+
+    if ( tempcx == 0 )
+    {
+        tempax = pVBInfo->VGAHDE ;
+        tempbx = pVBInfo->HDE ;
+    }
+    else
+    {
+        tempax = pVBInfo->VGAVDE ;
+        tempbx = pVBInfo->VDE ;
+    }
+
+    if ( tempax < tempbx )
+        return &EnlargeTap4Timing[ 0 ] ;
+    else if( tempax == tempbx )
+        return &NoScaleTap4Timing[ 0 ] ;       /* 1:1 */
+    else
+        Tap4TimingPtr = NTSCTap4Timing ;       /* NTSC */
+
+    if ( pVBInfo->TVInfo & SetPALTV )
+        Tap4TimingPtr = PALTap4Timing ;
+
+
+    if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+    {
+        if ( pVBInfo->TVInfo & SetYPbPrMode525i )
+            Tap4TimingPtr = YPbPr525iTap4Timing ;
+        if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+            Tap4TimingPtr = YPbPr525pTap4Timing ;
+        if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+            Tap4TimingPtr = YPbPr750pTap4Timing ;
+    }
+
+    if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+        Tap4TimingPtr = HiTVTap4Timing ;
+
+    i = 0 ;
+    while( Tap4TimingPtr[ i ].DE != 0xFFFF )
+    {
+        if ( Tap4TimingPtr[ i ].DE == tempax )
+            break ;
+        i++ ;
+    }
+    return &Tap4TimingPtr[ i ] ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetTap4Regs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT i ,
+           j ;
+
+    XGI301C_Tap4TimingStruct *Tap4TimingPtr ;
+
+    if ( !( pVBInfo->VBType & VB_XGI301C ) )
+        return ;
+
+#ifndef Tap4
+    XGINew_SetRegAND( pVBInfo->Part2Port , 0x4E , 0xEB ) ;     /* Disable Tap4 */
+#else            /* Tap4 Setting */
+
+    Tap4TimingPtr = XGI_GetTap4Ptr( 0 , pVBInfo) ;  /* Set Horizontal Scaling */
+    for( i = 0x80 , j = 0 ; i <= 0xBF ; i++ , j++ )
+        XGINew_SetReg1( pVBInfo->Part2Port , i , Tap4TimingPtr->Reg[ j ] ) ;
+
+    if ( ( pVBInfo->VBInfo & SetCRT2ToTV ) && ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) )
+    {
+        Tap4TimingPtr = XGI_GetTap4Ptr( 1 , pVBInfo);  /* Set Vertical Scaling */
+        for( i = 0xC0 , j = 0 ; i < 0xFF ; i++ , j++ )
+            XGINew_SetReg1( pVBInfo->Part2Port , i , Tap4TimingPtr->Reg[ j ] ) ;
+    }
+
+    if ( ( pVBInfo->VBInfo & SetCRT2ToTV ) && ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) )
+        XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x14 , 0x04 ) ;       /* Enable V.Scaling */
+    else
+        XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x14 , 0x10 ) ;       /* Enable H.Scaling */
+#endif
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGroup3 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGroup3(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT i;
+    UCHAR *tempdi;
+    USHORT  modeflag;
+
+    if(ModeNo<=0x13)
+    {
+        modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;      /* si+St_ResInfo */
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;     /* si+Ext_ResInfo */
+    }
+
+
+    XGINew_SetReg1(pVBInfo->Part3Port,0x00,0x00);
+    if(pVBInfo->TVInfo&SetPALTV)
+    {
+        XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xFA);
+        XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xC8);
+    }
+    else
+    {
+        XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xF5);
+        XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xB7);
+    }
+
+    if(!(pVBInfo->VBInfo&SetCRT2ToTV))
+    {
+        return;
+    }
+
+    if(pVBInfo->TVInfo&SetPALMTV)
+    {
+        XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xFA);
+        XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xC8);
+        XGINew_SetReg1(pVBInfo->Part3Port,0x3D,0xA8);
+    }
+
+    if((pVBInfo->VBInfo&SetCRT2ToHiVisionTV)|| (pVBInfo->VBInfo&SetCRT2ToYPbPr))
+    {
+        if(pVBInfo->TVInfo & SetYPbPrMode525i)
+        {
+            return;
+        }
+        tempdi=pVBInfo->HiTVGroup3Data;
+        if(pVBInfo->SetFlag&TVSimuMode)
+        {
+            tempdi=pVBInfo->HiTVGroup3Simu;
+            if(!(modeflag&Charx8Dot))
+            {
+                tempdi=pVBInfo->HiTVGroup3Text;
+            }
+        }
+
+        if(pVBInfo->TVInfo & SetYPbPrMode525p)
+        {
+            tempdi=pVBInfo->Ren525pGroup3;
+        }
+        if(pVBInfo->TVInfo & SetYPbPrMode750p)
+        {
+             tempdi=pVBInfo->Ren750pGroup3;
+        }
+
+        for(i=0;i<=0x3E;i++)
+        {
+            XGINew_SetReg1(pVBInfo->Part3Port,i,tempdi[i]);
+        }
+        if(pVBInfo->VBType&VB_XGI301C)  /* Marcovision */
+        {
+            if(pVBInfo->TVInfo & SetYPbPrMode525p)
+            {
+                XGINew_SetReg1(pVBInfo->Part3Port,0x28,0x3f);
+            }
+        }
+    }
+    return;
+}  /* {end of XGI_SetGroup3} */
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGroup4 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempax ,
+           tempcx ,
+           tempbx ,
+           modeflag ,
+           temp ,
+           temp2 ;
+
+    ULONG tempebx ,
+          tempeax ,
+          templong ;
+
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;  /* si+St_ResInfo */
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
+    }
+
+    temp = pVBInfo->RVBHCFACT ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x13 , temp ) ;
+
+    tempbx = pVBInfo->RVBHCMAX ;
+    temp = tempbx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x14 , temp ) ;
+    temp2 = ( ( tempbx & 0xFF00 ) >> 8 ) << 7 ;
+    tempcx = pVBInfo->VGAHT - 1 ;
+    temp = tempcx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x16 , temp ) ;
+
+    temp =( ( tempcx & 0xFF00 ) >> 8 ) << 3 ;
+    temp2 |= temp ;
+
+    tempcx = pVBInfo->VGAVT - 1 ;
+    if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) )
+    {
+        tempcx -= 5 ;
+    }
+
+    temp = tempcx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x17 , temp ) ;
+    temp = temp2 | ( ( tempcx & 0xFF00 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x15 , temp ) ;
+    XGINew_SetRegOR( pVBInfo->Part4Port , 0x0D , 0x08 ) ;
+    tempcx = pVBInfo->VBInfo ;
+    tempbx = pVBInfo->VGAHDE ;
+
+    if ( modeflag & HalfDCLK )
+    {
+        tempbx = tempbx >> 1 ;
+    }
+
+    if ( XGI_IsLCDDualLink( pVBInfo ) )
+        tempbx = tempbx >> 1 ;
+
+    if(tempcx&SetCRT2ToHiVisionTV)
+    {
+        temp=0;
+        if(tempbx<=1024)
+            temp=0xA0;
+       if(tempbx == 1280)
+          temp = 0xC0;
+    }
+    else if(tempcx&SetCRT2ToTV)
+    {
+         temp=0xA0;
+         if(tempbx <= 800)
+             temp=0x80;
+    }
+    else
+    {
+        temp=0x80;
+        if(pVBInfo->VBInfo&SetCRT2ToLCD)
+        {
+            temp=0;
+            if(tempbx>800)
+                temp=0x60;
+        }
+    }
+
+    if ( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
+    {
+        temp = 0x00 ;
+        if ( pVBInfo->VGAHDE == 1280 )
+            temp = 0x40 ;
+        if ( pVBInfo->VGAHDE == 1024 )
+           temp = 0x20 ;
+    }
+    XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0E , ~0xEF , temp ) ;
+
+    tempebx = pVBInfo->VDE ;
+
+    if ( tempcx & SetCRT2ToHiVisionTV )
+    {
+        if ( !( temp & 0xE000 ) )
+            tempbx = tempbx >> 1 ;
+    }
+
+    tempcx = pVBInfo->RVBHRS ;
+    temp = tempcx & 0x00FF ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x18 , temp );
+
+    tempeax = pVBInfo->VGAVDE ;
+    tempcx |= 0x04000 ;
+
+
+    if ( tempeax <= tempebx )
+    {
+        tempcx=(tempcx&(~0x4000));
+        tempeax = pVBInfo->VGAVDE ;
+    }
+    else
+    {
+        tempeax -= tempebx ;
+    }
+
+
+    templong = ( tempeax * 256 * 1024 ) % tempebx ;
+    tempeax = ( tempeax * 256 * 1024 ) / tempebx ;
+    tempebx = tempeax ;
+
+    if ( templong != 0 )
+    {
+        tempebx++ ;
+    }
+
+
+    temp = ( USHORT )( tempebx & 0x000000FF ) ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x1B , temp ) ;
+
+    temp = ( USHORT )( ( tempebx & 0x0000FF00 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x1A , temp ) ;
+    tempbx = ( USHORT )( tempebx >> 16 ) ;
+    temp = tempbx & 0x00FF ;
+    temp = temp << 4 ;
+    temp |= ( ( tempcx & 0xFF00 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x19 , temp ) ;
+
+    /* 301b */
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        temp = 0x0028 ;
+        XGINew_SetReg1( pVBInfo->Part4Port , 0x1C , temp ) ;
+        tempax = pVBInfo->VGAHDE ;
+        if ( modeflag & HalfDCLK )
+        {
+            tempax = tempax >> 1 ;
+        }
+
+        if ( XGI_IsLCDDualLink( pVBInfo ) )
+            tempax = tempax >> 1 ;
+
+        /* if((pVBInfo->VBInfo&(SetCRT2ToLCD))||((pVBInfo->TVInfo&SetYPbPrMode525p)||(pVBInfo->TVInfo&SetYPbPrMode750p))) { */
+        if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+        {
+            if ( tempax > 800 )
+                tempax -= 800 ;
+        }
+        else
+        {
+            if ( pVBInfo->VGAHDE > 800 )
+            {
+                if ( pVBInfo->VGAHDE == 1024 )
+                    tempax = ( tempax * 25 / 32 ) - 1 ;
+                else
+                    tempax = ( tempax * 20 / 32 ) - 1 ;
+            }
+        }
+        tempax -= 1 ;
+
+/*
+        if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToHiVisionTV ) )
+        {
+            if ( pVBInfo->VBType & VB_XGI301LV )
+            {
+                if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
+                {
+                    if ( pVBInfo->VGAHDE > 800 )
+                    {
+                        if ( pVBInfo->VGAHDE == 1024 )
+                            tempax = ( tempax * 25 / 32 ) - 1 ;
+                        else
+                            tempax = ( tempax * 20 / 32 ) - 1 ;
+                    }
+                }
+            }
+            else
+            {
+                if ( pVBInfo->VGAHDE > 800 )
+                {
+                    if ( pVBInfo->VGAHDE == 1024 )
+                        tempax = ( tempax * 25 / 32 ) - 1 ;
+                    else
+                        tempax = ( tempax * 20 / 32 ) - 1 ;
+                }
+            }
+        }
+*/
+
+        temp = ( tempax & 0xFF00 ) >> 8 ;
+        temp = ( ( temp & 0x0003 ) << 4 ) ;
+        XGINew_SetReg1( pVBInfo->Part4Port , 0x1E , temp ) ;
+        temp = ( tempax & 0x00FF ) ;
+        XGINew_SetReg1( pVBInfo->Part4Port , 0x1D , temp ) ;
+
+        if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToHiVisionTV ) )
+        {
+            if ( pVBInfo->VGAHDE > 800 )
+            {
+                XGINew_SetRegOR( pVBInfo->Part4Port , 0x1E , 0x08 ) ;
+            }
+        }
+        temp = 0x0036 ;
+
+        if ( pVBInfo->VBInfo & SetCRT2ToTV )
+        {
+            if ( !( pVBInfo->TVInfo & ( NTSC1024x768 | SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
+            {
+                temp |= 0x0001 ;
+                if ( ( pVBInfo->VBInfo & SetInSlaveMode ) && ( !( pVBInfo->TVInfo & TVSimuMode ) ) )
+                    temp &= ( ~0x0001 ) ;
+            }
+        }
+
+        XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x1F , 0x00C0 , temp ) ;
+        tempbx = pVBInfo->HT ;
+        if ( XGI_IsLCDDualLink( pVBInfo ) )
+            tempbx = tempbx >> 1 ;
+        tempbx = ( tempbx >> 1 ) - 2 ;
+        temp = ( ( tempbx & 0x0700 ) >> 8 ) << 3 ;
+        XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x21 , 0x00C0 , temp ) ;
+        temp = tempbx & 0x00FF ;
+        XGINew_SetReg1( pVBInfo->Part4Port , 0x22 , temp ) ;
+    }
+    /* end 301b */
+
+    if ( pVBInfo->ISXPDOS == 0 )
+        XGI_SetCRT2VCLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGroup5 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGroup5( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT Pindex ,
+           Pdata ;
+
+    Pindex = pVBInfo->Part5Port ;
+    Pdata = pVBInfo->Part5Port + 1 ;
+    if ( pVBInfo->ModeType == ModeVGA )
+    {
+        if ( !( pVBInfo->VBInfo & ( SetInSlaveMode | LoadDACFlag | CRT2DisplayFlag ) ) )
+        {
+            XGINew_EnableCRT2(pVBInfo) ;
+            /* LoadDAC2(pVBInfo->Part5Port,ModeNo,ModeIdIndex); */
+        }
+    }
+    return ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLcdPtr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void* XGI_GetLcdPtr( USHORT BX , USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT i ,
+           tempdx ,
+           tempcx ,
+           tempbx ,
+           tempal ,
+           modeflag ,
+           table ;
+
+    XGI330_LCDDataTablStruct *tempdi = 0 ;
+
+
+    tempbx = BX;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+        tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+        tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
+    }
+
+    tempal = tempal & 0x0f ;
+
+    if ( tempbx <= 1 )         /* ExpLink */
+    {
+        if ( ModeNo <= 0x13 )
+        {
+            tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ; /* find no Ext_CRT2CRTC2 */
+        }
+        else
+        {
+            tempal= pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
+        }
+
+        if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+        {
+            if ( ModeNo <= 0x13 )
+                tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC2 ;
+            else
+                tempal= pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC2 ;
+        }
+
+        if ( tempbx & 0x01 )
+            tempal = ( tempal >> 4 ) ;
+
+        tempal = ( tempal & 0x0f ) ;
+    }
+
+    tempcx = LCDLenList[ tempbx ] ;    /* mov cl,byte ptr cs:LCDLenList[bx] */
+
+    if ( pVBInfo->LCDInfo & EnableScalingLCD ) /* ScaleLCD */
+    {
+        if ( ( tempbx == 5 ) || ( tempbx ) == 7 )
+            tempcx = LCDDesDataLen2 ;
+        else if ( ( tempbx == 3 ) || ( tempbx == 8 ) )
+            tempcx = LVDSDesDataLen2 ;
+    }
+    /* mov di, word ptr cs:LCDDataList[bx] */
+    /* tempdi=pVideoMemory[LCDDataList+tempbx*2]|(pVideoMemory[LCDDataList+tempbx*2+1]<<8); */
+
+    switch( tempbx )
+    {
+        case 0:
+            tempdi = XGI_EPLLCDCRT1Ptr_H ;
+            break ;
+        case 1:
+            tempdi = XGI_EPLLCDCRT1Ptr_V ;
+             break ;
+        case 2:
+            tempdi = XGI_EPLLCDDataPtr ;
+            break ;
+        case 3:
+            tempdi = XGI_EPLLCDDesDataPtr ;
+            break ;
+        case 4:
+            tempdi = XGI_LCDDataTable ;
+            break ;
+        case 5:
+            tempdi = XGI_LCDDesDataTable ;
+            break ;
+        case 6:
+            tempdi = XGI_EPLCHLCDRegPtr ;
+            break ;
+        case 7:
+        case 8:
+        case 9:
+            tempdi = 0 ;
+            break ;
+        default:
+        break ;
+    }
+
+    if ( tempdi == 0x00 )  /* OEMUtil */
+        return 0 ;
+
+    table = tempbx ;
+    i = 0 ;
+
+    while( tempdi[ i ].PANELID != 0xff )
+    {
+        tempdx = pVBInfo->LCDResInfo ;
+        if ( tempbx & 0x0080 )     /* OEMUtil */
+        {
+            tempbx &= ( ~0x0080 ) ;
+            tempdx = pVBInfo->LCDTypeInfo ;
+        }
+
+        if ( pVBInfo->LCDInfo & EnableScalingLCD )
+        tempdx &= ( ~PanelResInfo ) ;
+
+        if ( tempdi[ i ].PANELID == tempdx )
+        {
+            tempbx = tempdi[ i ].MASK ;
+            tempdx = pVBInfo->LCDInfo ;
+
+            if ( ModeNo <= 0x13 )         /* alan 09/10/2003 */
+                tempdx |= SetLCDStdMode ;
+
+            if ( modeflag & HalfDCLK )
+                tempdx |= SetLCDLowResolution ;
+
+            tempbx &= tempdx;
+            if ( tempbx == tempdi[ i ].CAP )
+                break ;
+        }
+        i++ ;
+    }
+
+    if ( table == 0 )
+    {
+        switch( tempdi[ i ].DATAPTR )
+        {
+            case 0:
+                return &XGI_LVDSCRT11024x768_1_H[ tempal ] ;
+                break ;
+            case 1:
+                return &XGI_LVDSCRT11024x768_2_H[ tempal ] ;
+                break ;
+            case 2:
+                return &XGI_LVDSCRT11280x1024_1_H[ tempal ] ;
+                break ;
+            case 3:
+                return &XGI_LVDSCRT11280x1024_2_H[ tempal ] ;
+                break ;
+            case 4:
+                return &XGI_LVDSCRT11400x1050_1_H[ tempal ] ;
+                break ;
+            case 5:
+                return &XGI_LVDSCRT11400x1050_2_H[ tempal ] ;
+                break ;
+            case 6:
+                return &XGI_LVDSCRT11600x1200_1_H[ tempal ] ;
+                break ;
+            case 7:
+                return &XGI_LVDSCRT11024x768_1_Hx75[ tempal ] ;
+                break ;
+            case 8:
+                return &XGI_LVDSCRT11024x768_2_Hx75[ tempal ] ;
+                break ;
+            case 9:
+                return &XGI_LVDSCRT11280x1024_1_Hx75[ tempal ] ;
+                break ;
+            case 10:
+                return &XGI_LVDSCRT11280x1024_2_Hx75[ tempal ] ;
+                break ;
+            default:
+                break ;
+        }
+    }
+    else if ( table == 1 )
+    {
+        switch( tempdi[ i ].DATAPTR )
+        {
+            case 0:
+                return &XGI_LVDSCRT11024x768_1_V[ tempal ] ;
+                break ;
+            case 1:
+                return &XGI_LVDSCRT11024x768_2_V[ tempal ] ;
+                break ;
+            case 2:
+                return &XGI_LVDSCRT11280x1024_1_V[ tempal ] ;
+                break ;
+            case 3:
+                return &XGI_LVDSCRT11280x1024_2_V[ tempal ] ;
+                break ;
+            case 4:
+                return &XGI_LVDSCRT11400x1050_1_V[ tempal ] ;
+                break ;
+            case 5:
+                return &XGI_LVDSCRT11400x1050_2_V[ tempal ] ;
+                break ;
+            case 6:
+                return &XGI_LVDSCRT11600x1200_1_V[ tempal ] ;
+                break ;
+            case 7:
+                return &XGI_LVDSCRT11024x768_1_Vx75[ tempal ] ;
+                break ;
+            case 8:
+                return &XGI_LVDSCRT11024x768_2_Vx75[ tempal ] ;
+                break ;
+            case 9:
+                return &XGI_LVDSCRT11280x1024_1_Vx75[ tempal ] ;
+                break ;
+            case 10:
+                return &XGI_LVDSCRT11280x1024_2_Vx75[ tempal ] ;
+                break ;
+            default:
+                break ;
+        }
+    }
+    else if ( table == 2 )
+    {
+        switch( tempdi[ i ].DATAPTR )
+        {
+            case 0:
+                return &XGI_LVDS1024x768Data_1[ tempal ] ;
+                break ;
+            case 1:
+                return &XGI_LVDS1024x768Data_2[ tempal ] ;
+                break ;
+            case 2:
+                return &XGI_LVDS1280x1024Data_1[ tempal ] ;
+                break ;
+            case 3:
+                return &XGI_LVDS1280x1024Data_2[ tempal ] ;
+                break ;
+            case 4:
+                return &XGI_LVDS1400x1050Data_1[ tempal ] ;
+                break ;
+            case 5:
+                return &XGI_LVDS1400x1050Data_2[ tempal ] ;
+                break ;
+            case 6:
+                return &XGI_LVDS1600x1200Data_1[ tempal ] ;
+                break ;
+            case 7:
+                return &XGI_LVDSNoScalingData[ tempal ] ;
+                break ;
+            case 8:
+                return &XGI_LVDS1024x768Data_1x75[ tempal ] ;
+                break ;
+            case 9:
+                return &XGI_LVDS1024x768Data_2x75[ tempal ] ;
+                break ;
+            case 10:
+                return &XGI_LVDS1280x1024Data_1x75[ tempal ] ;
+                break ;
+            case 11:
+                return &XGI_LVDS1280x1024Data_2x75[ tempal ] ;
+                break ;
+            case 12:
+                return &XGI_LVDSNoScalingDatax75[ tempal ] ;
+                break ;
+            default:
+                break ;
+        }
+    }
+    else if ( table == 3 )
+    {
+        switch( tempdi[ i ].DATAPTR )
+        {
+            case 0:
+                return &XGI_LVDS1024x768Des_1[ tempal ] ;
+                break ;
+            case 1:
+                return &XGI_LVDS1024x768Des_3[ tempal ] ;
+                break ;
+            case 2:
+                return &XGI_LVDS1024x768Des_2[ tempal ] ;
+                break ;
+            case 3:
+                return &XGI_LVDS1280x1024Des_1[ tempal ] ;
+                break ;
+            case 4:
+                return &XGI_LVDS1280x1024Des_2[ tempal ] ;
+                break ;
+            case 5:
+                return &XGI_LVDS1400x1050Des_1[ tempal ] ;
+                break ;
+            case 6:
+                return &XGI_LVDS1400x1050Des_2[ tempal ] ;
+                break ;
+            case 7:
+                return &XGI_LVDS1600x1200Des_1[ tempal ] ;
+                break ;
+            case 8:
+                return &XGI_LVDSNoScalingDesData[ tempal ] ;
+                break ;
+            case 9:
+                return &XGI_LVDS1024x768Des_1x75[ tempal ] ;
+                break ;
+            case 10:
+                return &XGI_LVDS1024x768Des_3x75[ tempal ] ;
+                break ;
+            case 11:
+                return &XGI_LVDS1024x768Des_2x75[ tempal ] ;
+                break;
+            case 12:
+                return &XGI_LVDS1280x1024Des_1x75[ tempal ] ;
+                break ;
+            case 13:
+                return &XGI_LVDS1280x1024Des_2x75[ tempal ] ;
+                break ;
+            case 14:
+                return &XGI_LVDSNoScalingDesDatax75[ tempal ] ;
+                break ;
+            default:
+                break ;
+        }
+    }
+    else if ( table == 4 )
+    {
+        switch( tempdi[ i ].DATAPTR )
+        {
+            case 0:
+                return &XGI_ExtLCD1024x768Data[ tempal ] ;
+                break ;
+            case 1:
+                return &XGI_StLCD1024x768Data[ tempal ] ;
+                break ;
+            case 2:
+                return &XGI_CetLCD1024x768Data[ tempal ] ;
+                break ;
+            case 3:
+                return &XGI_ExtLCD1280x1024Data[ tempal ] ;
+                break ;
+            case 4:
+                return &XGI_StLCD1280x1024Data[ tempal ] ;
+                break ;
+            case 5:
+                return &XGI_CetLCD1280x1024Data[ tempal ] ;
+                break ;
+            case 6:
+                return &XGI_ExtLCD1400x1050Data[ tempal ] ;
+                break ;
+            case 7:
+                return &XGI_StLCD1400x1050Data[ tempal ] ;
+                break ;
+            case 8:
+                return &XGI_CetLCD1400x1050Data[ tempal ] ;
+                break ;
+            case 9:
+                return &XGI_ExtLCD1600x1200Data[ tempal ] ;
+                break  ;
+            case 10:
+                return &XGI_StLCD1600x1200Data[ tempal ] ;
+                break ;
+            case 11:
+                return &XGI_NoScalingData[ tempal ] ;
+                break ;
+            case 12:
+                return &XGI_ExtLCD1024x768x75Data[ tempal ] ;
+                break ;
+            case 13:
+                return &XGI_ExtLCD1024x768x75Data[ tempal ] ;
+                break ;
+            case 14:
+                return &XGI_CetLCD1024x768x75Data[ tempal ] ;
+                break ;
+            case 15:
+                 return &XGI_ExtLCD1280x1024x75Data[ tempal ] ;
+                break ;
+            case 16:
+                return &XGI_StLCD1280x1024x75Data[ tempal ] ;
+                break;
+            case 17:
+                return &XGI_CetLCD1280x1024x75Data[ tempal ] ;
+                break;
+            case 18:
+                return &XGI_NoScalingDatax75[ tempal ] ;
+                break ;
+            default:
+                break ;
+        }
+    }
+    else if ( table == 5 )
+    {
+        switch( tempdi[ i ].DATAPTR )
+        {
+            case 0:
+                return &XGI_ExtLCDDes1024x768Data[ tempal ] ;
+                break ;
+            case 1:
+                return &XGI_StLCDDes1024x768Data[ tempal ] ;
+                break ;
+            case 2:
+                return &XGI_CetLCDDes1024x768Data[ tempal ] ;
+                break ;
+            case 3:
+                if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+                    return &XGI_ExtLCDDLDes1280x1024Data[ tempal ] ;
+                else
+                    return &XGI_ExtLCDDes1280x1024Data[ tempal ] ;
+                break ;
+            case 4:
+                if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+                    return &XGI_StLCDDLDes1280x1024Data[ tempal ] ;
+                else
+                    return &XGI_StLCDDes1280x1024Data[ tempal ] ;
+                break ;
+            case 5:
+                if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+                    return &XGI_CetLCDDLDes1280x1024Data[ tempal ] ;
+                else
+                    return &XGI_CetLCDDes1280x1024Data[ tempal ] ;
+                break ;
+            case 6:
+                if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+                    return &XGI_ExtLCDDLDes1400x1050Data[ tempal ] ;
+                else
+                    return &XGI_ExtLCDDes1400x1050Data[ tempal ] ;
+                break ;
+            case 7:
+                if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+                    return &XGI_StLCDDLDes1400x1050Data[ tempal ] ;
+                else
+                    return &XGI_StLCDDes1400x1050Data[ tempal ] ;
+                break ;
+            case 8:
+                return &XGI_CetLCDDes1400x1050Data[ tempal ] ;
+                break ;
+            case 9:
+                return &XGI_CetLCDDes1400x1050Data2[ tempal ] ;
+                break ;
+            case 10:
+                if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+                    return &XGI_ExtLCDDLDes1600x1200Data[ tempal ] ;
+                else
+                    return &XGI_ExtLCDDes1600x1200Data[ tempal ] ;
+                break ;
+            case 11:
+                if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+                    return &XGI_StLCDDLDes1600x1200Data[ tempal ] ;
+                else
+                    return &XGI_StLCDDes1600x1200Data[ tempal ] ;
+                break ;
+            case 12:
+                return &XGI_NoScalingDesData[ tempal ] ;
+                break;
+            case 13:
+                return &XGI_ExtLCDDes1024x768x75Data[ tempal ] ;
+                break ;
+            case 14:
+                return &XGI_StLCDDes1024x768x75Data[ tempal ] ;
+                break ;
+            case 15:
+                return &XGI_CetLCDDes1024x768x75Data[ tempal ] ;
+                break ;
+            case 16:
+                if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+                    return &XGI_ExtLCDDLDes1280x1024x75Data[ tempal ] ;
+                else
+                    return &XGI_ExtLCDDes1280x1024x75Data[ tempal ] ;
+                break ;
+            case 17:
+                if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+                    return &XGI_StLCDDLDes1280x1024x75Data[ tempal ] ;
+                else
+                    return &XGI_StLCDDes1280x1024x75Data[ tempal ] ;
+                break ;
+            case 18:
+                if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+                    return &XGI_CetLCDDLDes1280x1024x75Data[ tempal ] ;
+                else
+                    return &XGI_CetLCDDes1280x1024x75Data[ tempal ] ;
+                break ;
+            case 19:
+                return &XGI_NoScalingDesDatax75[ tempal ] ;
+                break ;
+            default:
+                break ;
+        }
+    }
+    else if ( table == 6 )
+    {
+        switch( tempdi[ i ].DATAPTR )
+        {
+            case 0:
+                return &XGI_CH7017LV1024x768[ tempal ] ;
+                break ;
+            case 1:
+                return &XGI_CH7017LV1400x1050[ tempal ] ;
+                break ;
+            default:
+                break ;
+        }
+    }
+    return 0 ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetTVPtr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void* XGI_GetTVPtr (USHORT BX,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT i , tempdx , tempbx , tempal , modeflag , table ;
+    XGI330_TVDataTablStruct *tempdi = 0 ;
+
+    tempbx = BX ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+        tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+        tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
+    }
+
+    tempal = tempal & 0x3f ;
+    table = tempbx ;
+
+    switch( tempbx )
+    {
+        case 0:
+            tempdi = 0 ;       /*EPLCHTVCRT1Ptr_H;*/
+            if ( pVBInfo->IF_DEF_CH7007 == 1 )
+            {
+                tempdi = XGI_EPLCHTVCRT1Ptr;
+            }
+            break ;
+        case 1:
+            tempdi = 0 ;       /*EPLCHTVCRT1Ptr_V;*/
+            if ( pVBInfo->IF_DEF_CH7007 == 1 )
+            {
+                tempdi = XGI_EPLCHTVCRT1Ptr;
+            }
+            break ;
+        case 2:
+            tempdi = XGI_EPLCHTVDataPtr ;
+            break ;
+        case 3:
+            tempdi = 0 ;
+            break ;
+        case 4:
+            tempdi = XGI_TVDataTable ;
+            break ;
+        case 5:
+            tempdi = 0 ;
+            break ;
+        case 6:
+            tempdi = XGI_EPLCHTVRegPtr ;
+            break ;
+        default:
+            break ;
+    }
+
+    if ( tempdi == 0x00 )  /* OEMUtil */
+        return( 0 ) ;
+
+    tempdx = pVBInfo->TVInfo ;
+
+    if ( pVBInfo->VBInfo & SetInSlaveMode )
+        tempdx = tempdx | SetTVLockMode ;
+
+    if ( modeflag & HalfDCLK )
+        tempdx = tempdx | SetTVLowResolution ;
+
+    i = 0 ;
+
+    while( tempdi[ i ].MASK != 0xffff )
+    {
+        if ( ( tempdx & tempdi[ i ].MASK ) == tempdi[ i ].CAP )
+            break ;
+        i++ ;
+    }
+
+    if ( table == 0x00 ) /* 07/05/22 */
+    {
+#ifdef WIN2000
+        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+        {
+          switch( tempdi[ i ].DATAPTR )
+          {
+            case 0:
+                return &CH7007TVCRT1UNTSC_H[ tempal ] ;
+                break ;
+            case 1:
+                return &CH7007TVCRT1ONTSC_H[ tempal ] ;
+                break ;
+            case 2:
+                return &CH7007TVCRT1UPAL_H[ tempal ] ;
+                break ;
+            case 3:
+                return &CH7007TVCRT1OPAL_H[ tempal ] ;
+                break ;
+            default:
+                break ;
+          }
+        }
+#endif
+    }
+    else if ( table == 0x01 )
+    {
+#ifdef WIN2000
+        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+        {
+          switch( tempdi[ i ].DATAPTR )
+          {
+            case 0:
+                return &CH7007TVCRT1UNTSC_V[ tempal ] ;
+                break ;
+            case 1:
+                return &CH7007TVCRT1ONTSC_V[ tempal ] ;
+                break ;
+            case 2:
+                return &CH7007TVCRT1UPAL_V[ tempal ] ;
+                break ;
+            case 3:
+                return &CH7007TVCRT1OPAL_V[ tempal ] ;
+                break ;
+            default:
+                break ;
+          }
+        }
+#endif
+    }
+    else if ( table == 0x04 )
+    {
+        switch( tempdi[ i ].DATAPTR )
+        {
+            case 0:
+                return &XGI_ExtPALData[ tempal ] ;
+               break ;
+            case 1:
+                return &XGI_ExtNTSCData[ tempal ] ;
+               break ;
+           case 2:
+               return &XGI_StPALData[ tempal ] ;
+               break ;
+            case 3:
+               return &XGI_StNTSCData[ tempal ] ;
+               break ;
+           case 4:
+               return &XGI_ExtHiTVData[ tempal ] ;
+               break ;
+           case 5:
+               return &XGI_St2HiTVData[ tempal ] ;
+               break ;
+           case 6:
+               return &XGI_ExtYPbPr525iData[ tempal ] ;
+               break ;
+           case 7:
+               return &XGI_ExtYPbPr525pData[ tempal ] ;
+               break ;
+           case 8:
+               return &XGI_ExtYPbPr750pData[ tempal ] ;
+               break ;
+           case 9:
+               return &XGI_StYPbPr525iData[ tempal ] ;
+               break ;
+           case 10:
+               return &XGI_StYPbPr525pData[ tempal ] ;
+               break ;
+           case 11:
+               return &XGI_StYPbPr750pData[ tempal ] ;
+               break;
+            case 12:   /* avoid system hang */
+               return &XGI_ExtNTSCData[ tempal ] ;
+               break ;
+            case 13:
+               return &XGI_St1HiTVData[ tempal ] ;
+               break ;
+            default:
+                break ;
+        }
+    }
+    else if( table == 0x02 )
+    {
+        switch( tempdi[ i ].DATAPTR )
+        {
+            case 0:
+                return &XGI_CHTVUNTSCData[ tempal ] ;
+                break ;
+            case 1:
+               return &XGI_CHTVONTSCData[ tempal ] ;
+                break ;
+            case 2:
+                return &XGI_CHTVUPALData[ tempal ] ;
+                break ;
+            case 3:
+                return &XGI_CHTVOPALData[ tempal ] ;
+                break ;
+            default:
+                break ;
+        }
+    }
+    else if( table == 0x06 )
+    {
+#ifdef WIN2000
+        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+        {
+          /* VideoDebugPrint((0, "XGI_GetTVPtr: pVBInfo->IF_DEF_CH7007==1\n")); */
+          switch( tempdi[ i ].DATAPTR )
+          {
+            case 0:
+                return &CH7007TVReg_UNTSC[ tempal ] ;
+                break ;
+            case 1:
+                return &CH7007TVReg_ONTSC[ tempal ] ;
+                break ;
+            case 2:
+                return &CH7007TVReg_UPAL[ tempal ] ;
+                break ;
+            case 3:
+                return &CH7007TVReg_OPAL[ tempal ] ;
+                break ;
+            default:
+                break ;
+          }
+        }
+        else
+        {
+            switch( tempdi[ i ].DATAPTR )
+            {
+              case 0:
+                return &XGI_CHTVRegUNTSC[ tempal ] ;
+                break ;
+              case 1:
+                return &XGI_CHTVRegONTSC[ tempal ] ;
+                break ;
+              case 2:
+                return &XGI_CHTVRegUPAL[ tempal ] ;
+                break ;
+              case 3:
+                return &XGI_CHTVRegOPAL[ tempal ] ;
+                break ;
+              default:
+                break ;
+            }
+        }
+#endif
+    }
+    return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_BacklightByDrv */
+/* Input : */
+/* Output : TRUE -> Skip backlight control */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_BacklightByDrv( PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR tempah ;
+
+    tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x3A ) ;
+    if ( tempah & BacklightControlBit )
+        return TRUE ;
+    else
+        return FALSE ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_FirePWDDisable */
+/* Input : */
+/* Output : */
+/* Description : Turn off VDD & Backlight : Fire disable procedure */
+/* --------------------------------------------------------------------- */
+/*
+void XGI_FirePWDDisable( PVB_DEVICE_INFO pVBInfo )
+{
+    XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x26 , 0x00 , 0xFC ) ;
+}
+*/
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_FirePWDEnable */
+/* Input : */
+/* Output : */
+/* Description : Turn on VDD & Backlight : Fire enable procedure */
+/* --------------------------------------------------------------------- */
+void XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo )
+{
+    XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x26 , 0x03 , 0xFC ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_EnableGatingCRT */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x40 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisableGatingCRT */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x00 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetPanelDelay */
+/* Input : */
+/* Output : */
+/* Description : */
+/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */
+/* : bl : 2 ; T2 : the duration signal on and Vdd on */
+/* : bl : 3 ; T3 : the duration between CPL off and signal off */
+/* : bl : 4 ; T4 : the duration signal off and Vdd off */
+/* --------------------------------------------------------------------- */
+void XGI_SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT index ;
+
+    index = XGI_GetLCDCapPtr(pVBInfo) ;
+
+    if ( tempbl == 1 )
+        XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S1, pVBInfo ) ;
+
+    if ( tempbl == 2 )
+        XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S2, pVBInfo ) ;
+
+    if ( tempbl == 3 )
+        XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S3, pVBInfo ) ;
+
+    if ( tempbl == 4 )
+        XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S4, pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetPanelPower */
+/* Input : */
+/* Output : */
+/* Description : */
+/* I/O : ah = 0011b = 03h ; Backlight on, Power on */
+/* = 0111b = 07h ; Backlight on, Power off */
+/* = 1011b = 0Bh ; Backlight off, Power on */
+/* = 1111b = 0Fh ; Backlight off, Power off */
+/* --------------------------------------------------------------------- */
+void XGI_SetPanelPower(USHORT tempah,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+{
+    if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x26 , tempbl , tempah ) ;
+    else
+        XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x11 , tempbl , tempah ) ;
+}
+
+UCHAR XG21GPIODataTransfer(UCHAR ujDate)
+{
+    UCHAR  ujRet = 0;
+    UCHAR  i = 0;
+
+    for (i=0; i<8; i++)
+       {
+       ujRet = ujRet << 1;
+       /* ujRet |= GETBITS(ujDate >> i, 0:0); */
+        ujRet |= (ujDate >> i) & 1;
+    }
+
+       return ujRet;
+}
+
+/*----------------------------------------------------------------------------*/
+/* output                                                                     */
+/*      bl[5] : LVDS signal                                                   */
+/*      bl[1] : LVDS backlight                                                */
+/*      bl[0] : LVDS VDD                                                      */
+/*----------------------------------------------------------------------------*/
+UCHAR XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR CR4A,temp;
+
+    CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+    XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x23 ) ; /* enable GPIO write */
+
+    temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
+
+    temp = XG21GPIODataTransfer(temp);
+    temp &= 0x23;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x4A , CR4A ) ;
+    return temp;
+}
+
+/*----------------------------------------------------------------------------*/
+/* output                                                                     */
+/*      bl[5] : LVDS signal                                                   */
+/*      bl[1] : LVDS backlight                                                */
+/*      bl[0] : LVDS VDD                                                      */
+/*----------------------------------------------------------------------------*/
+UCHAR XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR CR4A,CRB4,temp;
+
+    CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+    XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x0C ) ; /* enable GPIO write */
+
+    temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
+
+    temp &= 0x0C;
+    temp >>= 2;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x4A , CR4A ) ;
+    CRB4 = XGINew_GetReg1( pVBInfo->P3d4 , 0xB4 ) ;
+    temp |= ((CRB4&0x04)<<3);
+    return temp;
+}
+/*----------------------------------------------------------------------------*/
+/* input                                                                      */
+/*      bl[5] : 1;LVDS signal on                                              */
+/*      bl[1] : 1;LVDS backlight on                                           */
+/*      bl[0] : 1:LVDS VDD on                                                 */
+/*      bh: 100000b : clear bit 5, to set bit5                                */
+/*          000010b : clear bit 1, to set bit1                                */
+/*          000001b : clear bit 0, to set bit0                                */
+/*----------------------------------------------------------------------------*/
+void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR CR4A,temp;
+
+    CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+    tempbh &= 0x23;
+    tempbl &= 0x23;
+    XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~tempbh ) ; /* enable GPIO write */
+
+    if (tempbh&0x20)
+    {
+      temp = (tempbl>>4)&0x02;
+
+      XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~0x02 , temp) ; /* CR B4[1] */
+
+    }
+
+    temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
+
+    temp = XG21GPIODataTransfer(temp);
+    temp &= ~tempbh;
+    temp |= tempbl;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x48 , temp ) ;
+}
+
+void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR CR4A,temp;
+    USHORT tempbh0,tempbl0;
+
+    tempbh0 = tempbh;
+    tempbl0 = tempbl;
+    tempbh0 &= 0x20;
+    tempbl0 &= 0x20;
+    tempbh0 >>= 3;
+    tempbl0 >>= 3;
+
+    if (tempbh&0x20)
+    {
+      temp = (tempbl>>4)&0x02;
+
+      XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~0x02 , temp) ; /* CR B4[1] */
+
+    }
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~tempbh0 , tempbl0 ) ;
+
+    CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+    tempbh &= 0x03;
+    tempbl &= 0x03;
+    tempbh <<= 2;
+    tempbl <<= 2;                                       /* GPIOC,GPIOD */
+    XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~tempbh ) ; /* enable GPIO write */
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~tempbh , tempbl ) ;
+}
+
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT index ;
+
+    index = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
+    if (index<sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct))
+    {
+      return index;
+    }
+    return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_XG21SetPanelDelay */
+/* Input : */
+/* Output : */
+/* Description : */
+/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */
+/* : bl : 2 ; T2 : the duration signal on and Vdd on */
+/* : bl : 3 ; T3 : the duration between CPL off and signal off */
+/* : bl : 4 ; T4 : the duration signal off and Vdd off */
+/* --------------------------------------------------------------------- */
+void XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT index ;
+
+    index = XGI_GetLVDSOEMTableIndex( pVBInfo );
+    if ( tempbl == 1 )
+        XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S1, pVBInfo ) ;
+
+    if ( tempbl == 2 )
+        XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S2, pVBInfo ) ;
+
+    if ( tempbl == 3 )
+        XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S3, pVBInfo ) ;
+
+    if ( tempbl == 4 )
+        XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S4, pVBInfo ) ;
+}
+
+BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT xres ,
+           yres ,
+           colordepth ,
+           modeflag ,
+           resindex ,
+           lvdstableindex;
+
+    resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+    if ( ModeNo <= 0x13 )
+    {
+        xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+        yres = pVBInfo->StResInfo[ resindex ].VTotal ;
+        modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;    /* si+St_ResInfo */
+    }
+    else
+    {
+        xres = pVBInfo->ModeResInfo[ resindex ].HTotal ;                         /* xres->ax */
+        yres = pVBInfo->ModeResInfo[ resindex ].VTotal ;                         /* yres->bx */
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */
+    }
+
+    if ( !( modeflag & Charx8Dot ) )
+    {
+        xres /= 9;
+        xres *= 8;
+    }
+
+    if ( ModeNo > 0x13 )
+    {
+        if ( ( ModeNo>0x13 ) && ( modeflag & HalfDCLK ) )
+        {
+          xres *=  2 ;
+        }
+        if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) )
+        {
+          yres *=  2 ;
+        }
+    }
+
+    lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+    if ( xres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE) )
+      return FALSE;
+
+    if ( yres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE) )
+      return FALSE;
+
+    if ( ModeNo > 0x13 )
+    {
+      if ( ( xres != (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE) ) ||
+           ( yres != (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE)) )
+      {
+          colordepth = XGI_GetColorDepth( ModeNo , ModeIdIndex, pVBInfo ) ;
+          if ( colordepth > 2 )
+          {
+            return FALSE;
+          }
+      }
+    }
+    return TRUE;
+}
+
+void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR temp;
+
+    temp = XGINew_GetReg1( pVBInfo->P3d4  , 0x37 ) ;  /* D[0] 1: 18bit */
+    temp = ( temp & 1 ) << 6;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0x40 , temp ) ;      /* SR06[6] 18bit Dither */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0xc0 , temp | 0x80 ) ;  /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: dual 12bits */
+
+}
+
+void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
+{
+    UCHAR temp;
+
+    temp = XGINew_GetReg1( pVBInfo->P3d4  , 0x37 ) ;  /* D[1:0] 01: 18bit, 00: dual 12, 10: single 24 */
+    temp = ( temp & 3 ) << 6;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0xc0 , temp & 0x80 ) ;  /* SR06[7]0: dual 12/1: single 24 [6] 18bit Dither <= 0 h/w recommend */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0xc0 , temp | 0x80 ) ;  /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: 24bits */
+
+}
+
+void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR temp,Miscdata;
+    USHORT xres ,
+           yres ,
+           modeflag ,
+           resindex ,
+           lvdstableindex ;
+    USHORT LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE;
+    USHORT LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE;
+    USHORT value;
+
+    lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+
+    temp = (UCHAR) ( ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8 ) ) >> 8 );
+    temp &= LCDPolarity;
+    Miscdata =(UCHAR) XGINew_GetReg2(pVBInfo->P3cc) ;
+
+    XGINew_SetReg3( pVBInfo->P3c2 , (Miscdata & 0x3F) | temp ) ;
+
+    temp = (UCHAR) ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x80 , temp&0x80 ) ;      /* SR35[7] FP VSync polarity */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , ~0x20 , (temp&0x40)>>1 ) ;   /* SR30[5] FP HSync polarity */
+
+    XGI_SetXG21FPBits(pVBInfo);
+    resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+    if ( ModeNo <= 0x13 )
+    {
+        xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+        yres = pVBInfo->StResInfo[ resindex ].VTotal ;
+        modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;    /* si+St_ResInfo */
+    }
+    else
+    {
+        xres = pVBInfo->ModeResInfo[ resindex ].HTotal ;                         /* xres->ax */
+        yres = pVBInfo->ModeResInfo[ resindex ].VTotal ;                         /* yres->bx */
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */
+    }
+
+    if (!( modeflag & Charx8Dot ))
+      xres = xres * 8 / 9;
+
+    LVDSHT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
+
+    LVDSHBS = xres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE - xres ) / 2 ;
+    if ( ( ModeNo<=0x13 ) && ( modeflag & HalfDCLK ) )
+    {
+      LVDSHBS -=  xres/4 ;
+    }
+    if (LVDSHBS > LVDSHT) LVDSHBS -= LVDSHT ;
+
+    LVDSHRS = LVDSHBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP ;
+    if (LVDSHRS > LVDSHT) LVDSHRS -= LVDSHT ;
+
+    LVDSHRE = LVDSHRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC ;
+    if (LVDSHRE > LVDSHT) LVDSHRE -= LVDSHT ;
+
+    LVDSHBE = LVDSHBS + LVDSHT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE ;
+
+    LVDSVT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
+
+    LVDSVBS = yres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE - yres ) / 2 ;
+    if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) )
+    {
+      LVDSVBS +=  yres/2 ;
+    }
+    if (LVDSVBS > LVDSVT) LVDSVBS -= LVDSVT ;
+
+    LVDSVRS = LVDSVBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP ;
+    if (LVDSVRS > LVDSVT) LVDSVRS -= LVDSVT ;
+
+    LVDSVRE = LVDSVRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC ;
+    if (LVDSVRE > LVDSVT) LVDSVRE -= LVDSVT ;
+
+    LVDSVBE = LVDSVBS + LVDSVT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE ;
+
+    temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp & 0x7f ) ;             /* Unlock CRTC */
+
+    if (!( modeflag & Charx8Dot ))
+    {
+        XGINew_SetRegOR( pVBInfo->P3c4 , 0x1 , 0x1 ) ;
+    }
+
+    /* HT SR0B[1:0] CR00 */
+    value = ( LVDSHT >> 3 ) - 5;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x03 , ( value & 0x300 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x0 , (value & 0xFF) ) ;
+
+    /* HBS SR0B[5:4] CR02 */
+    value = ( LVDSHBS >> 3 ) - 1;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x30 , ( value & 0x300 ) >> 4 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x2 , (value & 0xFF) ) ;
+
+    /* HBE SR0C[1:0] CR05[7] CR03[4:0] */
+    value = ( LVDSHBE >> 3 ) - 1;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x03 , ( value & 0xC0 ) >> 6 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x80 , ( value & 0x20 ) << 2 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x03 , ~0x1F , value & 0x1F ) ;
+
+    /* HRS SR0B[7:6] CR04 */
+    value = ( LVDSHRS >> 3 ) + 2;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0xC0 , ( value & 0x300 ) >> 2 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x4 , (value & 0xFF) ) ;
+
+    /* Panel HRS SR2F[1:0] SR2E[7:0]  */
+    value--;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0x03 , ( value & 0x300 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , (value & 0xFF) ) ;
+
+    /* HRE SR0C[2] CR05[4:0] */
+    value = ( LVDSHRE >> 3 ) + 2;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x04 , ( value & 0x20 ) >> 3 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x1F , value & 0x1F ) ;
+
+    /* Panel HRE SR2F[7:2]  */
+    value--;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0xFC , value << 2 ) ;
+
+    /* VT SR0A[0] CR07[5][0] CR06 */
+    value = LVDSVT - 2 ;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x01 , ( value & 0x400 ) >> 10 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x01 , ( value & 0x100 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x06 , (value & 0xFF) ) ;
+
+    /* VBS SR0A[2] CR09[5] CR07[3] CR15 */
+    value = LVDSVBS - 1 ;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x04 , ( value & 0x400 ) >> 8 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x09 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x08 , ( value & 0x100 ) >> 5 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , (value & 0xFF) ) ;
+
+    /* VBE SR0A[4] CR16 */
+    value = LVDSVBE - 1;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x10 , ( value & 0x100 ) >> 4 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , (value & 0xFF) ) ;
+
+    /* VRS SR0A[3] CR7[7][2] CR10 */
+    value = LVDSVRS - 1 ;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x08 , ( value & 0x400 ) >> 7 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x80 , ( value & 0x200 ) >> 2 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x04 , ( value & 0x100 ) >> 6 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x10 , (value & 0xFF) ) ;
+
+    /* Panel VRS SR3F[1:0] SR34[7:0] SR33[0] */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0x03 , ( value & 0x600 ) >> 9 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , (value >> 1) & 0xFF ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x33 , ~0x01 , value & 0x01 ) ;
+
+    /* VRE SR0A[5] CR11[3:0] */
+    value = LVDSVRE - 1;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x20 , ( value & 0x10 ) << 1 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , ~0x0F , value & 0x0F ) ;
+
+    /* Panel VRE SR3F[7:2] */ /* SR3F[7] has to be 0, h/w bug */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , ( value << 2 ) & 0x7C ) ;
+
+    for ( temp=0, value = 0; temp < 3; temp++)
+    {
+
+        XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , value ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2) ;
+        value += 0x10;
+    }
+
+    if (!( modeflag & Charx8Dot ))
+    {
+        XGINew_GetReg2( pVBInfo->P3da ) ;           /* reset 3da */
+        XGINew_SetReg3( pVBInfo->P3c0 , 0x13 ) ;    /* set index */
+        XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ;    /* set data, panning = 0, shift left 1 dot*/
+
+        XGINew_GetReg2( pVBInfo->P3da ) ;           /* Enable Attribute */
+        XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ;
+
+        XGINew_GetReg2( pVBInfo->P3da ) ;           /* reset 3da */
+    }
+
+
+}
+
+/* no shadow case */
+void XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR temp,Miscdata;
+    USHORT xres ,
+           yres ,
+           modeflag ,
+           resindex ,
+           lvdstableindex ;
+    USHORT LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE;
+    USHORT LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE;
+    USHORT value;
+
+    lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+    temp = (UCHAR) ( ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8 ) ) >> 8 );
+    temp &= LCDPolarity;
+    Miscdata =(UCHAR) XGINew_GetReg2(pVBInfo->P3cc) ;
+
+    XGINew_SetReg3( pVBInfo->P3c2 , (Miscdata & 0x3F) | temp ) ;
+
+    temp = (UCHAR) ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x80 , temp&0x80 ) ;      /* SR35[7] FP VSync polarity */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , ~0x20 , (temp&0x40)>>1 ) ;   /* SR30[5] FP HSync polarity */
+
+    XGI_SetXG27FPBits(pVBInfo);
+    resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+    if ( ModeNo <= 0x13 )
+    {
+        xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+        yres = pVBInfo->StResInfo[ resindex ].VTotal ;
+        modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;    /* si+St_ResInfo */
+    }
+    else
+    {
+        xres = pVBInfo->ModeResInfo[ resindex ].HTotal ;                         /* xres->ax */
+        yres = pVBInfo->ModeResInfo[ resindex ].VTotal ;                         /* yres->bx */
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */
+    }
+
+    if (!( modeflag & Charx8Dot ))
+      xres = xres * 8 / 9;
+
+    LVDSHT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
+
+    LVDSHBS = xres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE - xres ) / 2 ;
+    if ( ( ModeNo<=0x13 ) && ( modeflag & HalfDCLK ) )
+    {
+      LVDSHBS -=  xres/4 ;
+    }
+    if (LVDSHBS > LVDSHT) LVDSHBS -= LVDSHT ;
+
+    LVDSHRS = LVDSHBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP ;
+    if (LVDSHRS > LVDSHT) LVDSHRS -= LVDSHT ;
+
+    LVDSHRE = LVDSHRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC ;
+    if (LVDSHRE > LVDSHT) LVDSHRE -= LVDSHT ;
+
+    LVDSHBE = LVDSHBS + LVDSHT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE ;
+
+    LVDSVT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
+
+    LVDSVBS = yres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE - yres ) / 2 ;
+    if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) )
+    {
+      LVDSVBS +=  yres/2 ;
+    }
+    if (LVDSVBS > LVDSVT) LVDSVBS -= LVDSVT ;
+
+    LVDSVRS = LVDSVBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP ;
+    if (LVDSVRS > LVDSVT) LVDSVRS -= LVDSVT ;
+
+    LVDSVRE = LVDSVRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC ;
+    if (LVDSVRE > LVDSVT) LVDSVRE -= LVDSVT ;
+
+    LVDSVBE = LVDSVBS + LVDSVT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE ;
+
+    temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp & 0x7f ) ;             /* Unlock CRTC */
+
+    if (!( modeflag & Charx8Dot ))
+    {
+        XGINew_SetRegOR( pVBInfo->P3c4 , 0x1 , 0x1 ) ;
+    }
+
+    /* HT SR0B[1:0] CR00 */
+    value = ( LVDSHT >> 3 ) - 5;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x03 , ( value & 0x300 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x0 , (value & 0xFF) ) ;
+
+    /* HBS SR0B[5:4] CR02 */
+    value = ( LVDSHBS >> 3 ) - 1;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x30 , ( value & 0x300 ) >> 4 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x2 , (value & 0xFF) ) ;
+
+    /* HBE SR0C[1:0] CR05[7] CR03[4:0] */
+    value = ( LVDSHBE >> 3 ) - 1;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x03 , ( value & 0xC0 ) >> 6 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x80 , ( value & 0x20 ) << 2 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x03 , ~0x1F , value & 0x1F ) ;
+
+    /* HRS SR0B[7:6] CR04 */
+    value = ( LVDSHRS >> 3 ) + 2;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0xC0 , ( value & 0x300 ) >> 2 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x4 , (value & 0xFF) ) ;
+
+    /* Panel HRS SR2F[1:0] SR2E[7:0]  */
+    value--;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0x03 , ( value & 0x300 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , (value & 0xFF) ) ;
+
+    /* HRE SR0C[2] CR05[4:0] */
+    value = ( LVDSHRE >> 3 ) + 2;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x04 , ( value & 0x20 ) >> 3 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x1F , value & 0x1F ) ;
+
+    /* Panel HRE SR2F[7:2]  */
+    value--;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0xFC , value << 2 ) ;
+
+    /* VT SR0A[0] CR07[5][0] CR06 */
+    value = LVDSVT - 2 ;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x01 , ( value & 0x400 ) >> 10 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x01 , ( value & 0x100 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x06 , (value & 0xFF) ) ;
+
+    /* VBS SR0A[2] CR09[5] CR07[3] CR15 */
+    value = LVDSVBS - 1 ;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x04 , ( value & 0x400 ) >> 8 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x09 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x08 , ( value & 0x100 ) >> 5 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , (value & 0xFF) ) ;
+
+    /* VBE SR0A[4] CR16 */
+    value = LVDSVBE - 1;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x10 , ( value & 0x100 ) >> 4 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , (value & 0xFF) ) ;
+
+    /* VRS SR0A[3] CR7[7][2] CR10 */
+    value = LVDSVRS - 1 ;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x08 , ( value & 0x400 ) >> 7 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x80 , ( value & 0x200 ) >> 2 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x04 , ( value & 0x100 ) >> 6 ) ;
+    XGINew_SetReg1( pVBInfo->P3d4 , 0x10 , (value & 0xFF) ) ;
+
+    /* Panel VRS SR35[2:0] SR34[7:0] */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x07 , ( value & 0x700 ) >> 8 ) ;
+    XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , value & 0xFF ) ;
+
+    /* VRE SR0A[5] CR11[3:0] */
+    value = LVDSVRE - 1;
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x20 , ( value & 0x10 ) << 1 ) ;
+    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , ~0x0F , value & 0x0F ) ;
+
+    /* Panel VRE SR3F[7:2] */
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , ( value << 2 ) & 0xFC ) ;
+
+    for ( temp=0, value = 0; temp < 3; temp++)
+    {
+
+        XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , value ) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1) ;
+        XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2) ;
+        value += 0x10;
+    }
+
+    if (!( modeflag & Charx8Dot ))
+    {
+        XGINew_GetReg2( pVBInfo->P3da ) ;           /* reset 3da */
+        XGINew_SetReg3( pVBInfo->P3c0 , 0x13 ) ;    /* set index */
+        XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ;    /* set data, panning = 0, shift left 1 dot*/
+
+        XGINew_GetReg2( pVBInfo->P3da ) ;           /* Enable Attribute */
+        XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ;
+
+        XGINew_GetReg2( pVBInfo->P3da ) ;           /* reset 3da */
+    }
+
+
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_IsLCDON */
+/* Input : */
+/* Output : FALSE : Skip PSC Control */
+/* TRUE: Disable PSC */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempax ;
+
+    tempax = pVBInfo->VBInfo ;
+    if ( tempax & SetCRT2ToDualEdge )
+        return FALSE ;
+    else if ( tempax & ( DisableCRT2Display | SwitchToCRT2 | SetSimuScanMode ) )
+        return TRUE ;
+
+    return FALSE ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_EnablePWD */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_EnablePWD(  PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT index ,
+           temp ;
+
+    index = XGI_GetLCDCapPtr(pVBInfo) ;
+    temp = pVBInfo->LCDCapList[ index ].PWD_2B ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x2B , temp ) ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x2C , pVBInfo->LCDCapList[ index ].PWD_2C ) ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x2D , pVBInfo->LCDCapList[ index ].PWD_2D ) ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x2E , pVBInfo->LCDCapList[ index ].PWD_2E ) ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x2F , pVBInfo->LCDCapList[ index ].PWD_2F ) ;
+    XGINew_SetRegOR( pVBInfo->Part4Port , 0x27 , 0x80 ) ;      /* enable PWD */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisablePWD */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo )
+{
+    XGINew_SetRegAND( pVBInfo->Part4Port , 0x27 , 0x7F ) ;     /* disable PWD */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisableChISLCD */
+/* Input : */
+/* Output : FALSE -> Not LCD Mode */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempbx ,
+           tempah ;
+
+    tempbx = pVBInfo->SetFlag & ( DisableChA | DisableChB ) ;
+    tempah = ~( ( USHORT )XGINew_GetReg1( pVBInfo->Part1Port  , 0x2E ) ) ;
+
+    if ( tempbx & ( EnableChA | DisableChA ) )
+    {
+        if ( !( tempah & 0x08 ) )              /* Chk LCDA Mode */
+            return FALSE ;
+    }
+
+    if ( !( tempbx & ( EnableChB | DisableChB ) ) )
+        return FALSE ;
+
+    if ( tempah & 0x01 )       /* Chk LCDB Mode */
+        return TRUE ;
+
+    return FALSE ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_EnableChISLCD */
+/* Input : */
+/* Output : 0 -> Not LCD mode */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempbx ,
+           tempah ;
+
+
+    tempbx = pVBInfo->SetFlag & ( EnableChA | EnableChB ) ;
+    tempah = ~( ( USHORT )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ) ;
+
+    if ( tempbx & ( EnableChA | DisableChA ) )
+    {
+        if ( !( tempah & 0x08 ) )              /* Chk LCDA Mode */
+            return FALSE ;
+    }
+
+    if ( !( tempbx & ( EnableChB | DisableChB ) ) )
+        return FALSE ;
+
+    if ( tempah & 0x01 )       /* Chk LCDB Mode */
+        return TRUE ;
+
+    return FALSE ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLCDCapPtr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetLCDCapPtr(  PVB_DEVICE_INFO pVBInfo )
+{
+    UCHAR tempal ,
+          tempah ,
+          tempbl ,
+          i ;
+
+    tempah = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
+    tempal = tempah & 0x0F ;
+    tempah = tempah & 0xF0 ;
+    i = 0 ;
+    tempbl =  pVBInfo->LCDCapList[ i ].LCD_ID ;
+
+    while( tempbl != 0xFF )
+    {
+        if ( tempbl & 0x80 )   /* OEMUtil */
+        {
+            tempal = tempah ;
+            tempbl = tempbl & ~( 0x80 ) ;
+        }
+
+        if ( tempal == tempbl )
+            break ;
+
+        i++ ;
+
+        tempbl = pVBInfo->LCDCapList[ i ].LCD_ID ;
+    }
+
+    return i ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLCDCapPtr1 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetLCDCapPtr1( PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempah ,
+           tempal ,
+           tempbl ,
+           i ;
+
+    tempal = pVBInfo->LCDResInfo ;
+    tempah = pVBInfo->LCDTypeInfo ;
+
+    i = 0 ;
+    tempbl =  pVBInfo->LCDCapList[ i ].LCD_ID;
+
+    while( tempbl != 0xFF )
+    {
+        if ( ( tempbl & 0x80 ) && ( tempbl != 0x80 ) )
+        {
+            tempal = tempah ;
+            tempbl &= ~0x80 ;
+        }
+
+        if ( tempal == tempbl )
+            break ;
+
+        i++ ;
+        tempbl = pVBInfo->LCDCapList[ i ].LCD_ID ;
+    }
+
+    if ( tempbl == 0xFF )
+    {
+        pVBInfo->LCDResInfo = Panel1024x768 ;
+        pVBInfo->LCDTypeInfo = 0 ;
+        i = 0 ;
+    }
+
+    return i ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLCDSync */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetLCDSync( USHORT* HSyncWidth , USHORT* VSyncWidth, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT Index ;
+
+    Index = XGI_GetLCDCapPtr(pVBInfo) ;
+    *HSyncWidth = pVBInfo->LCDCapList[ Index ].LCD_HSyncWidth ;
+    *VSyncWidth = pVBInfo->LCDCapList[ Index ].LCD_VSyncWidth ;
+
+    return ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_EnableBridge */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_EnableBridge( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempbl ,
+           tempah ;
+
+    if ( pVBInfo->SetFlag == Win9xDOSMode )
+    {
+        if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        {
+            XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
+            return ;
+        }
+        else  /* LVDS or CH7017 */
+            return ;
+    }
+
+
+    if ( HwDeviceExtension->jChipType < XG40 )
+    {
+        if ( !XGI_DisableChISLCD(pVBInfo) )
+        {
+            if ( ( XGI_EnableChISLCD(pVBInfo) ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
+            {
+                if ( pVBInfo->LCDInfo & SetPWDEnable )
+                {
+                    XGI_EnablePWD( pVBInfo);
+                }
+                else
+                {
+                    pVBInfo->LCDInfo &= ( ~SetPWDEnable ) ;
+                    if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+                    {
+                        tempbl = 0xFD ;
+                        tempah = 0x02 ;
+                    }
+                    else
+                    {
+                        tempbl = 0xFB ;
+                        tempah = 0x00 ;
+                    }
+
+                    XGI_SetPanelPower( tempah , tempbl, pVBInfo ) ;
+                    XGI_SetPanelDelay( 1,pVBInfo ) ;
+                }
+            }
+        }
+    }  /* Not 340 */
+
+
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        if ( !( pVBInfo->SetFlag & DisableChA ) )
+        {
+            if ( pVBInfo->SetFlag & EnableChA )
+            {
+                XGINew_SetReg1( pVBInfo->Part1Port , 0x1E , 0x20 ) ;  /* Power on */
+            }
+            else
+            {
+                if ( pVBInfo->VBInfo & SetCRT2ToDualEdge ) /* SetCRT2ToLCDA ) */
+                {
+                    XGINew_SetReg1(pVBInfo->Part1Port,0x1E,0x20);  /* Power on */
+                }
+            }
+        }
+
+        if ( !( pVBInfo->SetFlag & DisableChB ) )
+        {
+            if ( ( pVBInfo->SetFlag & EnableChB ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV | SetCRT2ToRAMDAC ) ) )
+            {
+                tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) ;
+                tempah &= 0xDF;
+                if ( pVBInfo->VBInfo & SetInSlaveMode )
+                {
+                    if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
+                        tempah |= 0x20 ;
+                }
+                XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , tempah ) ;
+                XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x20 ) ;
+
+
+                tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ;
+
+                if ( !( tempah & 0x80 ) )
+                    XGINew_SetRegOR( pVBInfo->Part1Port , 0x2E , 0x80 ) ;      /* BVBDOENABLE = 1 */
+
+                XGINew_SetRegAND( pVBInfo->Part1Port , 0x00 , 0x7F ) ;         /* BScreenOFF = 0 */
+            }
+        }
+
+        if ( ( pVBInfo->SetFlag & ( EnableChA | EnableChB ) ) || ( !( pVBInfo->VBInfo & DisableCRT2Display ) ) )
+        {
+            XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x00 , ~0xE0 , 0x20 ) ;   /* shampoo 0129 */
+            if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
+            {
+                if ( !XGI_DisableChISLCD(pVBInfo) )
+                {
+                    if ( XGI_EnableChISLCD( pVBInfo) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
+                        XGINew_SetRegAND( pVBInfo->Part4Port ,0x2A , 0x7F ) ;          /* LVDS PLL power on */
+                }
+                XGINew_SetRegAND( pVBInfo->Part4Port , 0x30 , 0x7F ) ;         /* LVDS Driver power on */
+            }
+        }
+
+        tempah = 0x00 ;
+
+        if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
+        {
+            tempah = 0xc0 ;
+
+            if ( !( pVBInfo->VBInfo & SetSimuScanMode ) )
+            {
+                if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+                {
+                    if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+                    {
+                        tempah = tempah & 0x40;
+                        if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+                            tempah = tempah ^ 0xC0 ;
+
+                        if ( pVBInfo->SetFlag & DisableChB )
+                            tempah &= 0xBF ;
+
+                        if ( pVBInfo->SetFlag & DisableChA )
+                            tempah &= 0x7F ;
+
+                        if ( pVBInfo->SetFlag & EnableChB )
+                            tempah |= 0x40 ;
+
+                        if ( pVBInfo->SetFlag & EnableChA )
+                            tempah |= 0x80 ;
+                    }
+                }
+            }
+        }
+
+        XGINew_SetRegOR( pVBInfo->Part4Port , 0x1F , tempah ) ;          /* EnablePart4_1F */
+
+        if ( pVBInfo->SetFlag & Win9xDOSMode )
+        {
+            XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
+            return ;
+        }
+
+        if ( !( pVBInfo->SetFlag & DisableChA ) )
+        {
+            XGI_VBLongWait( pVBInfo) ;
+            if ( !( pVBInfo->SetFlag & GatingCRT ) )
+            {
+                XGI_DisableGatingCRT( HwDeviceExtension, pVBInfo ) ;
+                XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
+                XGI_VBLongWait( pVBInfo) ;
+            }
+        }
+    }  /* 301 */
+    else       /* LVDS */
+    {
+        if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) )
+            XGINew_SetRegOR( pVBInfo->Part1Port , 0x1E , 0x20 ) ;              /* enable CRT2 */
+
+
+
+        tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ;
+        if ( !( tempah & 0x80 ) )
+            XGINew_SetRegOR( pVBInfo->Part1Port , 0x2E , 0x80 ) ;      /* BVBDOENABLE = 1 */
+
+        XGINew_SetRegAND(pVBInfo->Part1Port,0x00,0x7F);
+        XGI_DisplayOn( HwDeviceExtension, pVBInfo);
+    } /* End of VB */
+
+
+    if ( HwDeviceExtension->jChipType < XG40 )
+    {
+        if ( !XGI_EnableChISLCD(pVBInfo) )
+        {
+            if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+            {
+                if ( XGI_BacklightByDrv(pVBInfo) )
+                    return ;
+            }
+            else
+                return ;
+        }
+
+        if ( pVBInfo->LCDInfo & SetPWDEnable )
+        {
+            XGI_FirePWDEnable(pVBInfo) ;
+            return ;
+        }
+
+        XGI_SetPanelDelay( 2,pVBInfo ) ;
+
+        if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        {
+            tempah = 0x01 ;
+            tempbl = 0xFE ;            /* turn on backlght */
+        }
+        else
+        {
+            tempbl = 0xF7 ;
+            tempah = 0x00 ;
+        }
+        XGI_SetPanelPower( tempah , tempbl , pVBInfo) ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisableBridge */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempax ,
+           tempbx ,
+           tempah = 0 ,
+           tempbl = 0 ;
+
+    if ( pVBInfo->SetFlag == Win9xDOSMode )
+        return ;
+
+
+    if ( HwDeviceExtension->jChipType < XG40 )
+    {
+        if ( ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) || ( XGI_DisableChISLCD(pVBInfo) ) )
+        {
+            if ( !XGI_IsLCDON(pVBInfo) )
+            {
+                if ( pVBInfo->LCDInfo & SetPWDEnable )
+                    XGI_EnablePWD( pVBInfo) ;
+                else
+                {
+                    pVBInfo->LCDInfo &= ~SetPWDEnable ;
+                    XGI_DisablePWD(pVBInfo) ;
+                    if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+                    {
+                        tempbx = 0xFE ;  /* not 01h */
+                        tempax = 0 ;
+                    }
+                    else
+                    {
+                        tempbx = 0xF7 ;  /* not 08h */
+                        tempax = 0x08 ;
+                    }
+                    XGI_SetPanelPower( tempax , tempbx , pVBInfo) ;
+                    XGI_SetPanelDelay( 3,pVBInfo ) ;
+                }
+            }  /* end if(!XGI_IsLCDON(pVBInfo)) */
+        }
+    }
+
+/*  if ( CH7017 )
+    {
+        if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2toLCDA ) ) || ( XGI_DisableChISLCD(pVBInfo) ) )
+        {
+            if ( !XGI_IsLCDON(pVBInfo) )
+            {
+                if ( DISCHARGE )
+                {
+                    tempbx = XGINew_GetCH7005( 0x61 ) ;
+                    if ( tempbx < 0x01 )   //first time we power up
+                        XGINew_SetCH7005( 0x0066 ) ;   //and disable power sequence
+                    else
+                        XGINew_SetCH7005( 0x5f66 ) ; //leave VDD on - disable power
+                }
+            }
+        }
+    }        */
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B| VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        tempah = 0x3F ;
+        if ( !( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) ) )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+            {
+                if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+                {
+                    tempah = 0x7F;                     /* Disable Channel A */
+                    if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
+                        tempah = 0xBF ;                /* Disable Channel B */
+
+                    if ( pVBInfo->SetFlag & DisableChB )
+                        tempah &= 0xBF ;               /* force to disable Cahnnel */
+
+                    if ( pVBInfo->SetFlag & DisableChA )
+                        tempah &= 0x7F ;               /* Force to disable Channel B */
+                }
+            }
+        }
+
+        XGINew_SetRegAND( pVBInfo->Part4Port , 0x1F , tempah ) ;   /* disable part4_1f */
+
+        if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
+        {
+            if ( ( ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) || ( XGI_DisableChISLCD(pVBInfo) ) || ( XGI_IsLCDON(pVBInfo) ) )
+                XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x80 ) ;  /* LVDS Driver power down */
+        }
+
+        if ( ( pVBInfo->SetFlag & DisableChA ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetCRT2ToLCDA | SetSimuScanMode ) ) )
+        {
+            if ( pVBInfo->SetFlag & GatingCRT )
+                XGI_EnableGatingCRT( HwDeviceExtension, pVBInfo ) ;
+            XGI_DisplayOff( HwDeviceExtension, pVBInfo) ;
+        }
+
+        if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+        {
+            if ( ( pVBInfo->SetFlag & DisableChA ) || ( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
+                XGINew_SetRegAND( pVBInfo->Part1Port , 0x1e , 0xdf ) ;         /* Power down */
+        }
+
+        XGINew_SetRegAND( pVBInfo->P3c4 , 0x32 , 0xdf ) ;              /* disable TV as primary VGA swap */
+
+        if ( ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToDualEdge  ) ) )
+            XGINew_SetRegAND(pVBInfo->Part2Port,0x00,0xdf);
+
+        if ( ( pVBInfo->SetFlag & DisableChB ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) )
+        || ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) ) )
+            XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x80 ) ;      /* BScreenOff=1 */
+
+        if ( ( pVBInfo->SetFlag & DisableChB ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) )
+        || ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) || ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) )
+        {
+            tempah= XGINew_GetReg1( pVBInfo->Part1Port , 0x00 ) ;      /* save Part1 index 0 */
+            XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x10 ) ;      /* BTDAC = 1, avoid VB reset */
+            XGINew_SetRegAND( pVBInfo->Part1Port , 0x1E , 0xDF ) ;     /* disable CRT2 */
+            XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ;     /* restore Part1 index 0 */
+        }
+    }
+    else /* {301} */
+    {
+        if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV ) )
+        {
+            XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x80 ) ;      /* BScreenOff=1 */
+            XGINew_SetRegAND( pVBInfo->Part1Port , 0x1E , 0xDF ) ;     /* Disable CRT2 */
+            XGINew_SetRegAND( pVBInfo->P3c4 , 0x32 , 0xDF ) ;  /* Disable TV asPrimary VGA swap */
+        }
+
+        if ( pVBInfo->VBInfo & ( DisableCRT2Display | SetCRT2ToLCDA | SetSimuScanMode ) )
+            XGI_DisplayOff( HwDeviceExtension, pVBInfo) ;
+    }
+
+
+
+
+    if ( HwDeviceExtension->jChipType < XG40 )
+    {
+        if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) || ( XGI_DisableChISLCD(pVBInfo) ) || ( XGI_IsLCDON(pVBInfo) ) )
+        {
+            if ( pVBInfo->LCDInfo & SetPWDEnable )
+            {
+                if ( pVBInfo->LCDInfo & SetPWDEnable )
+                    XGI_BacklightByDrv(pVBInfo) ;
+                else
+                {
+                    XGI_SetPanelDelay( 4 ,pVBInfo) ;
+                    if ( pVBInfo->VBType & VB_XGI301LV )
+                    {
+                        tempbl = 0xFD ;
+                        tempah = 0x00 ;
+                    }
+                    else
+                    {
+                        tempbl = 0xFB ;
+                        tempah = 0x04 ;
+                    }
+                }
+            }
+            XGI_SetPanelPower( tempah , tempbl , pVBInfo) ;
+        }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetTVPtrIndex */
+/* Input : */
+/* Output : */
+/* Description : bx 0 : ExtNTSC */
+/* 1 : StNTSC */
+/* 2 : ExtPAL */
+/* 3 : StPAL */
+/* 4 : ExtHiTV */
+/* 5 : StHiTV */
+/* 6 : Ext525i */
+/* 7 : St525i */
+/* 8 : Ext525p */
+/* 9 : St525p */
+/* A : Ext750p */
+/* B : St750p */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetTVPtrIndex(  PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempbx = 0 ;
+
+    if ( pVBInfo->TVInfo & SetPALTV )
+        tempbx = 2 ;
+    if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
+        tempbx = 4 ;
+    if ( pVBInfo->TVInfo & SetYPbPrMode525i )
+        tempbx = 6 ;
+    if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+        tempbx = 8 ;
+    if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+        tempbx = 10 ;
+    if ( pVBInfo->TVInfo & TVSimuMode )
+        tempbx++ ;
+
+    return tempbx ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_OEM310Setting */
+/* Input : */
+/* Output : */
+/* Description : Customized Param. for 301 */
+/* --------------------------------------------------------------------- */
+void XGI_OEM310Setting( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+    if ( pVBInfo->SetFlag & Win9xDOSMode )
+        return ;
+
+    /* GetPart1IO(); */
+    XGI_SetDelayComp(pVBInfo) ;
+
+    if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+        XGI_SetLCDCap(pVBInfo) ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToTV )
+    {
+        /* GetPart2IO() */
+        XGI_SetPhaseIncr(pVBInfo) ;
+        XGI_SetYFilter( ModeNo , ModeIdIndex,pVBInfo ) ;
+        XGI_SetAntiFlicker( ModeNo , ModeIdIndex,pVBInfo ) ;
+
+        if ( pVBInfo->VBType&VB_XGI301)
+            XGI_SetEdgeEnhance( ModeNo , ModeIdIndex ,pVBInfo) ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetDelayComp */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetDelayComp( PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT index ;
+
+    UCHAR  tempah ,
+           tempbl ,
+           tempbh ;
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToTV | SetCRT2ToRAMDAC ) )
+        {
+            tempbl = 0;
+            tempbh = 0;
+
+            index = XGI_GetTVPtrIndex(pVBInfo ) ;           /* Get TV Delay */
+            tempbl = pVBInfo->XGI_TVDelayList[ index ] ;
+
+            if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+                tempbl = pVBInfo->XGI_TVDelayList2[ index ] ;
+
+            if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+                tempbl = tempbl >> 4 ;
+/*
+            if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+                tempbl = CRT2Delay1 ;                  // Get CRT2 Delay
+
+            if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+                tempbl = CRT2Delay2 ;
+*/
+            if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+            {
+                index = XGI_GetLCDCapPtr(pVBInfo) ;            /* Get LCD Delay */
+                tempbh=pVBInfo->LCDCapList[ index ].LCD_DelayCompensation ;
+
+                if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
+                     tempbl = tempbh ;
+            }
+
+            tempbl  &= 0x0F ;
+            tempbh  &= 0xF0 ;
+            tempah = XGINew_GetReg1( pVBInfo->Part1Port , 0x2D ) ;
+
+            if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) )  /* Channel B */
+            {
+                tempah &= 0xF0 ;
+                tempah |= tempbl ;
+            }
+
+            if ( pVBInfo->VBInfo & SetCRT2ToLCDA )             /* Channel A */
+            {
+                tempah &= 0x0F ;
+                tempah |= tempbh ;
+            }
+            XGINew_SetReg1(pVBInfo->Part1Port,0x2D,tempah);
+        }
+    }
+    else if ( pVBInfo->IF_DEF_LVDS == 1 )
+    {
+        tempbl = 0;
+        tempbh = 0;
+        if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+        {
+            tempah = pVBInfo->LCDCapList[ XGI_GetLCDCapPtr(pVBInfo) ].LCD_DelayCompensation ;          /* / Get LCD Delay */
+            tempah &= 0x0f ;
+            tempah = tempah << 4 ;
+            XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2D , 0x0f , tempah ) ;
+        }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLCDCap */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLCDCap( PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempcx ;
+
+    tempcx = pVBInfo->LCDCapList[ XGI_GetLCDCapPtr(pVBInfo) ].LCD_Capability ;
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        {                                      /* 301LV/302LV only */
+            /* Set 301LV Capability */
+            XGINew_SetReg1( pVBInfo->Part4Port , 0x24 , ( UCHAR )( tempcx & 0x1F ) ) ;
+       }
+        /* VB Driving */
+        XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~( ( EnableVBCLKDRVLOW | EnablePLLSPLOW ) >> 8 ) , ( USHORT )( ( tempcx & ( EnableVBCLKDRVLOW | EnablePLLSPLOW ) ) >> 8 ) ) ;
+    }
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+            XGI_SetLCDCap_B( tempcx,pVBInfo ) ;
+        else if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+            XGI_SetLCDCap_A( tempcx,pVBInfo ) ;
+
+        if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
+        {
+            if ( tempcx & EnableSpectrum )
+                SetSpectrum( pVBInfo) ;
+        }
+    }
+    else      /* LVDS,CH7017 */
+        XGI_SetLCDCap_A( tempcx, pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLCDCap_A */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLCDCap_A(USHORT tempcx,PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT temp ;
+
+    temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
+
+    if ( temp & LCDRGB18Bit )
+    {
+        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0x0F , ( USHORT )( 0x20 | ( tempcx & 0x00C0 ) ) ) ; /* Enable Dither */
+        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1A , 0x7F , 0x80 ) ;
+    }
+    else
+    {
+        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0x0F , ( USHORT )( 0x30 | ( tempcx & 0x00C0 ) ) ) ;
+        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1A , 0x7F , 0x00 ) ;
+    }
+
+/*
+    if ( tempcx & EnableLCD24bpp )     // 24bits
+    {
+        XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(USHORT)(0x30|(tempcx&0x00C0)) );
+        XGINew_SetRegANDOR(pVBInfo->Part1Port,0x1A,0x7F,0x00);
+    }
+    else
+    {
+        XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(USHORT)(0x20|(tempcx&0x00C0)) );//Enable Dither
+        XGINew_SetRegANDOR(pVBInfo->Part1Port,0x1A,0x7F,0x80);
+    }
+*/
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLCDCap_B */
+/* Input : cx -> LCD Capability */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLCDCap_B(USHORT tempcx,PVB_DEVICE_INFO pVBInfo)
+{
+    if ( tempcx & EnableLCD24bpp )     /* 24bits */
+        XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1A , 0xE0 , ( USHORT )( ( ( tempcx & 0x00ff ) >> 6 ) | 0x0c ) ) ;
+    else
+        XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1A , 0xE0 , ( USHORT )( ( ( tempcx & 0x00ff ) >> 6 ) | 0x18 ) ) ; /* Enable Dither */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : SetSpectrum */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void SetSpectrum( PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT index ;
+
+    index = XGI_GetLCDCapPtr(pVBInfo) ;
+
+    XGINew_SetRegAND( pVBInfo->Part4Port , 0x30 , 0x8F ) ;   /* disable down spectrum D[4] */
+    XGI_LongWait(pVBInfo) ;
+    XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x20 ) ;       /* reset spectrum */
+    XGI_LongWait(pVBInfo) ;
+
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , pVBInfo->LCDCapList[ index ].Spectrum_31 ) ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x32 , pVBInfo->LCDCapList[ index ].Spectrum_32 ) ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x33 , pVBInfo->LCDCapList[ index ].Spectrum_33 ) ;
+    XGINew_SetReg1( pVBInfo->Part4Port , 0x34 , pVBInfo->LCDCapList[ index ].Spectrum_34 ) ;
+    XGI_LongWait(pVBInfo) ;
+    XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x40 ) ; /* enable spectrum */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetAntiFlicker */
+/* Input : */
+/* Output : */
+/* Description : Set TV Customized Param. */
+/* --------------------------------------------------------------------- */
+void XGI_SetAntiFlicker( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempbx ,
+           index ;
+
+    UCHAR tempah ;
+
+    if (pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
+        return ;
+
+    tempbx = XGI_GetTVPtrIndex(pVBInfo ) ;
+    tempbx &= 0xFE ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        index = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVFlickerIndex ;
+    }
+    else
+    {
+        index = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVFlickerIndex ;
+    }
+
+    tempbx += index ;
+    tempah = TVAntiFlickList[ tempbx ] ;
+    tempah = tempah << 4 ;
+
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0x8F , tempah ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetEdgeEnhance */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetEdgeEnhance( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempbx ,
+           index ;
+
+    UCHAR tempah ;
+
+
+    tempbx = XGI_GetTVPtrIndex(pVBInfo ) ;
+    tempbx &= 0xFE ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        index = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVEdgeIndex ;
+    }
+    else
+    {
+        index = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVEdgeIndex ;
+    }
+
+    tempbx += index ;
+    tempah = TVEdgeList[ tempbx ] ;
+    tempah = tempah << 5 ;
+
+    XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x3A , 0x1F , tempah ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetPhaseIncr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetPhaseIncr( PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempbx ;
+
+    UCHAR tempcl ,
+          tempch ;
+
+    ULONG tempData ;
+
+    XGI_GetTVPtrIndex2( &tempbx , &tempcl , &tempch, pVBInfo ) ; /* bx, cl, ch */
+    tempData = TVPhaseList[ tempbx ] ;
+
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x31 , ( USHORT )( tempData & 0x000000FF ) ) ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x32 , ( USHORT )( ( tempData & 0x0000FF00 ) >> 8 ) ) ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x33 , ( USHORT )( ( tempData & 0x00FF0000 ) >> 16 ) ) ;
+    XGINew_SetReg1( pVBInfo->Part2Port , 0x34 , ( USHORT )( ( tempData & 0xFF000000 ) >> 24 ) ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetYFilter */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetYFilter( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempbx ,
+           index ;
+
+    UCHAR tempcl ,
+          tempch ,
+          tempal ,
+          *filterPtr ;
+
+    XGI_GetTVPtrIndex2( &tempbx , &tempcl , &tempch, pVBInfo ) ; /* bx, cl, ch */
+
+    switch( tempbx )
+    {
+        case 0x00:
+        case 0x04:
+            filterPtr = NTSCYFilter1 ;
+            break ;
+
+        case 0x01:
+            filterPtr = PALYFilter1 ;
+            break ;
+
+        case 0x02:
+        case 0x05:
+        case 0x0D:
+            filterPtr = PALMYFilter1 ;
+            break ;
+
+        case 0x03:
+            filterPtr = PALNYFilter1 ;
+            break ;
+
+        case 0x08:
+        case 0x0C:
+            filterPtr = NTSCYFilter2 ;
+            break ;
+
+        case 0x0A:
+            filterPtr = PALMYFilter2 ;
+            break ;
+
+        case 0x0B:
+            filterPtr = PALNYFilter2 ;
+            break ;
+
+        case 0x09:
+            filterPtr = PALYFilter2 ;
+            break ;
+
+        default:
+            return ;
+    }
+
+    if ( ModeNo <= 0x13 )
+        tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVYFilterIndex ;
+    else
+        tempal = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVYFilterIndex ;
+
+    if ( tempcl == 0 )
+        index = tempal * 4;
+    else
+        index = tempal * 7;
+
+    if ( ( tempcl == 0 ) && ( tempch == 1 ) )
+    {
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x35 , 0 ) ;
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x36 , 0 ) ;
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x37 , 0 ) ;
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x38 , filterPtr[ index++ ] ) ;
+    }
+    else
+    {
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x35 , filterPtr[ index++ ] ) ;
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x36 , filterPtr[ index++ ] ) ;
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x37 , filterPtr[ index++ ] ) ;
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x38 , filterPtr[ index++ ] ) ;
+    }
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x48 , filterPtr[ index++ ] ) ;
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x49 , filterPtr[ index++ ] ) ;
+        XGINew_SetReg1( pVBInfo->Part2Port , 0x4A , filterPtr[ index++ ] ) ;
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetTVPtrIndex2 */
+/* Input : */
+/* Output : bx 0 : NTSC */
+/* 1 : PAL */
+/* 2 : PALM */
+/* 3 : PALN */
+/* 4 : NTSC1024x768 */
+/* 5 : PAL-M 1024x768 */
+/* 6-7: reserved */
+/* cl 0 : YFilter1 */
+/* 1 : YFilter2 */
+/* ch 0 : 301A */
+/* 1 : 301B/302B/301LV/302LV */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetTVPtrIndex2(USHORT* tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo)
+{
+    *tempbx = 0 ;
+    *tempcl = 0 ;
+    *tempch = 0 ;
+
+    if ( pVBInfo->TVInfo & SetPALTV )
+        *tempbx = 1 ;
+
+    if ( pVBInfo->TVInfo & SetPALMTV )
+        *tempbx = 2 ;
+
+    if ( pVBInfo->TVInfo & SetPALNTV )
+        *tempbx = 3 ;
+
+    if ( pVBInfo->TVInfo & NTSC1024x768 )
+    {
+        *tempbx = 4 ;
+        if ( pVBInfo->TVInfo & SetPALMTV )
+            *tempbx = 5 ;
+    }
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        if ( ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) || ( pVBInfo->TVInfo & TVSimuMode ) )
+        {
+            *tempbx += 8 ;
+            *tempcl += 1 ;
+        }
+    }
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+        (*tempch)++ ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2ModeRegs */
+/* Input : */
+/* Output : */
+/* Description : Origin code for crt2group */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempbl ;
+    SHORT  tempcl ;
+
+    UCHAR  tempah ;
+
+    /* XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , 0x00 ) ; // fix write part1 index 0 BTDRAM bit Bug */
+    tempah=0;
+    if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
+    {
+        tempah=XGINew_GetReg1( pVBInfo->Part1Port , 0x00 ) ;
+        tempah &= ~0x10 ;      /* BTRAMDAC */
+        tempah |=  0x40 ;      /* BTRAM */
+
+        if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) )
+        {
+            tempah=0x40;       /* BTDRAM */
+            if ( ModeNo > 0x13 )
+            {
+                tempcl = pVBInfo->ModeType ;
+                tempcl -= ModeVGA ;
+                if ( tempcl >= 0 )
+                {
+                    tempah = ( 0x008 >> tempcl ) ;     /* BT Color */
+                    if ( tempah == 0 )
+                        tempah = 1 ;
+                    tempah |= 0x040 ;
+                }
+            }
+            if ( pVBInfo->VBInfo & SetInSlaveMode )
+                tempah ^= 0x50 ;       /* BTDAC */
+        }
+    }
+
+/*     0210 shampoo
+    if ( pVBInfo->VBInfo & DisableCRT2Display )
+    {
+        tempah = 0 ;
+    }
+
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ;
+    if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) )
+    {
+        tempcl = pVBInfo->ModeType ;
+        if ( ModeNo > 0x13 )
+        {
+            tempcl -= ModeVGA ;
+            if ( ( tempcl > 0 ) || ( tempcl == 0 ) )
+            {
+                tempah=(0x008>>tempcl) ;
+                if ( tempah == 0 )
+                    tempah = 1 ;
+                tempah |= 0x040;
+            }
+        }
+        else
+        {
+            tempah = 0x040 ;
+        }
+
+        if ( pVBInfo->VBInfo & SetInSlaveMode )
+        {
+            tempah = ( tempah ^ 0x050 ) ;
+        }
+    }
+*/
+
+    XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ;
+    tempah = 0x08 ;
+    tempbl = 0xf0 ;
+
+    if ( pVBInfo->VBInfo & DisableCRT2Display )
+        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
+    else
+    {
+        tempah = 0x00 ;
+        tempbl = 0xff ;
+
+        if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) )
+        {
+            if ( ( pVBInfo->VBInfo & SetCRT2ToLCDA ) && ( !( pVBInfo->VBInfo & SetSimuScanMode ) ) )
+            {
+                tempbl &= 0xf7 ;
+                tempah |= 0x01 ;
+                XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
+            }
+            else
+            {
+                if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+                {
+                    tempbl &= 0xf7 ;
+                    tempah |= 0x01 ;
+                }
+
+                if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) )
+                {
+                    tempbl &= 0xf8 ;
+                    tempah = 0x01 ;
+
+                    if ( !( pVBInfo->VBInfo & SetInSlaveMode ) )
+                        tempah |= 0x02 ;
+
+                    if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
+                    {
+                        tempah = tempah ^ 0x05 ;
+                        if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
+                            tempah = tempah ^ 0x01 ;
+                    }
+
+                    if ( !( pVBInfo->VBInfo & SetCRT2ToDualEdge ) )
+                        tempah |= 0x08 ;
+                    XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
+                }
+                else
+                    XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
+            }
+        }
+        else
+            XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
+    }
+
+    if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) )
+    {
+        tempah &= ( ~0x08 ) ;
+        if ( ( pVBInfo->ModeType == ModeVGA ) && ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) )
+        {
+            tempah |= 0x010 ;
+        }
+        tempah |= 0x080 ;
+
+        if ( pVBInfo->VBInfo & SetCRT2ToTV )
+        {
+            /* if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) ) */
+            /* { */
+            tempah |= 0x020 ;
+            if ( ModeNo > 0x13 )
+            {
+                if ( pVBInfo->VBInfo & DriverMode )
+                    tempah = tempah ^ 0x20 ;
+            }
+        /* } */
+        }
+
+        XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~0x0BF , tempah ) ;
+        tempah = 0 ;
+
+        if ( pVBInfo->LCDInfo & SetLCDDualLink )
+            tempah |= 0x40 ;
+
+        if ( pVBInfo->VBInfo & SetCRT2ToTV )
+        {
+            /* if ( ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) && ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) ) ) */
+            /* { */
+                if ( pVBInfo->TVInfo & RPLLDIV2XO )
+                    tempah |= 0x40 ;
+            /* } */
+        }
+
+        if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) )
+            tempah |= 0x80 ;
+
+        if ( pVBInfo->LCDResInfo == Panel1280x960 )
+            tempah |= 0x80 ;
+
+        XGINew_SetReg1( pVBInfo->Part4Port , 0x0C , tempah ) ;
+    }
+
+    if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+    {
+        tempah = 0 ;
+        tempbl = 0xfb ;
+
+        if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+        {
+            tempbl=0xff;
+            if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+                tempah |= 0x04 ; /* shampoo 0129 */
+        }
+
+        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x13 , tempbl , tempah ) ;
+        tempah = 0x00 ;
+        tempbl = 0xcf ;
+        if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+                tempah |= 0x30 ;
+        }
+
+        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2c , tempbl , tempah ) ;
+        tempah = 0 ;
+        tempbl = 0x3f ;
+
+        if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+                tempah |= 0xc0 ;
+        }
+        XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x21 , tempbl , tempah ) ;
+    }
+
+    tempah = 0 ;
+    tempbl = 0x7f ;
+    if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
+    {
+        tempbl = 0xff ;
+        if ( !( pVBInfo->VBInfo & SetCRT2ToDualEdge ) )
+            tempah |= 0x80 ;
+    }
+
+    XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x23 , tempbl , tempah ) ;
+
+    if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
+    {
+        if ( pVBInfo->LCDInfo & SetLCDDualLink )
+        {
+            XGINew_SetRegOR( pVBInfo->Part4Port , 0x27 , 0x20 ) ;
+            XGINew_SetRegOR( pVBInfo->Part4Port , 0x34 , 0x10 ) ;
+        }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_CloseCRTC */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_CloseCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempbx ;
+
+    tempbx = 0 ;
+
+    if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+        tempbx = 0x08A0 ;
+
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_OpenCRTC */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_OpenCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempbx ;
+
+    tempbx = 0 ;
+
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetRAMDAC2DATA */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetRAMDAC2DATA(USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempax ,
+           tempbx ,
+           temp1 ,
+           temp2 ,
+           modeflag = 0 ,
+           tempcx ,
+           StandTableIndex ,
+           CRT1Index ;
+
+    pVBInfo->RVBHCMAX = 1 ;
+    pVBInfo->RVBHCFACT = 1 ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+        StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
+        tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 0 ] ;
+        tempbx = pVBInfo->StandTable[StandTableIndex ].CRTC[ 6 ] ;
+        temp1 = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+        CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+        CRT1Index &= IndexMask ;
+        temp1 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 0 ] ;
+        temp2 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 5 ] ;
+       tempax = ( temp1 & 0xFF ) | ( ( temp2 & 0x03 ) << 8 ) ;
+        tempbx = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 8 ] ;
+        tempcx = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] << 8 ;
+       tempcx &= 0x0100 ;
+       tempcx = tempcx << 2 ;
+       tempbx |= tempcx;
+        temp1 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 9 ] ;
+    }
+
+    if ( temp1 & 0x01 )
+        tempbx |= 0x0100 ;
+
+    if ( temp1 & 0x20 )
+        tempbx |= 0x0200 ;
+    tempax += 5 ;
+
+    if ( modeflag & Charx8Dot )
+        tempax *= 8 ;
+    else
+        tempax *= 9 ;
+
+    pVBInfo->VGAHT = tempax ;
+    pVBInfo->HT = tempax ;
+    tempbx++ ;
+    pVBInfo->VGAVT = tempbx ;
+    pVBInfo->VT = tempbx ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetColorDepth */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetColorDepth(USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT ColorDepth[ 6 ] = { 1 , 2 , 4 , 4 , 6 , 8 } ;
+    SHORT  index ;
+    USHORT modeflag ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+    }
+
+    index=(modeflag&ModeInfoFlag)-ModeEGA;
+
+    if ( index < 0 )
+        index = 0 ;
+
+    return( ColorDepth[ index ] ) ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_UnLockCRT2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_UnLockCRT2( PXGI_HW_DEVICE_INFO HwDeviceExtension,  PVB_DEVICE_INFO pVBInfo )
+{
+
+    XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2f , 0xFF , 0x01 ) ;
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_LockCRT2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_LockCRT2( PXGI_HW_DEVICE_INFO HwDeviceExtension,  PVB_DEVICE_INFO pVBInfo )
+{
+
+    XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2F , 0xFE , 0x00 ) ;
+
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_EnableCRT2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_EnableCRT2( PVB_DEVICE_INFO pVBInfo)
+{
+    XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1E , 0xFF , 0x20 ) ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT i ,
+           j ;
+
+    ULONG temp ,
+          flag ;
+
+    flag = 0 ;
+//printk("XGINew_LCD_Wait_Time");
+//return;
+    for( i = 0 ; i < DelayTime ; i++ )
+    {
+        for( j = 0 ; j < 66 ; j++ )
+        {
+
+            temp =  XGINew_GetReg3( 0x61 ) ;
+
+            //temp &= 0x10000000;
+            temp &= 0x10;
+            if ( temp == flag )
+                continue ;
+
+            flag = temp ;
+        }
+    }
+}
+
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_BridgeIsOn */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_BridgeIsOn( PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT flag ;
+
+    if ( pVBInfo->IF_DEF_LVDS == 1 )
+    {
+        return( 1 ) ;
+    }
+    else
+    {
+        flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x00 ) ;
+        if ( ( flag == 1 ) || ( flag == 2 ) )
+            return( 1 ) ;      /* 301b */
+        else
+            return( 0 ) ;
+    }
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_LongWait */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_LongWait(PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT i ;
+
+    i = XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ;
+
+    if ( !( i & 0xC0 ) )
+    {
+        for( i = 0 ; i < 0xFFFF ; i++ )
+        {
+            if ( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x08 ) )
+                break ;
+        }
+
+        for( i = 0 ; i < 0xFFFF ; i++ )
+        {
+            if ( ( XGINew_GetReg2( pVBInfo->P3da ) & 0x08 ) )
+                break ;
+       }
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_VBLongWait */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_VBLongWait( PVB_DEVICE_INFO pVBInfo )
+{
+    USHORT tempal ,
+           temp ,
+           i ,
+           j ;
+return ;
+    if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) )
+    {
+        temp = 0 ;
+        for( i = 0 ; i < 3 ; i++ )
+        {
+            for( j = 0 ; j < 100 ; j++ )
+            {
+                tempal = XGINew_GetReg2( pVBInfo->P3da ) ;
+                if ( temp & 0x01 )
+                {                      /* VBWaitMode2 */
+                    if ( ( tempal & 0x08 ) )
+                    {
+                        continue ;
+                    }
+
+                    if ( !( tempal & 0x08 ) )
+                    {
+                        break ;
+                    }
+                }
+                else
+                {                      /* VBWaitMode1 */
+                    if ( !( tempal & 0x08 ) )
+                    {
+                        continue ;
+                    }
+
+                    if ( ( tempal & 0x08 ) )
+                    {
+                        break ;
+                    }
+                }
+            }
+            temp = temp ^ 0x01 ;
+        }
+    }
+    else
+    {
+        XGI_LongWait(pVBInfo) ;
+    }
+    return ;
+}
+
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVGAHT2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetVGAHT2( PVB_DEVICE_INFO pVBInfo )
+{
+    ULONG tempax ,
+          tempbx ;
+
+    tempbx = ( ( pVBInfo->VGAVT - pVBInfo->VGAVDE ) * pVBInfo->RVBHCMAX ) & 0xFFFF ;
+    tempax = ( pVBInfo->VT - pVBInfo->VDE ) * pVBInfo->RVBHCFACT ;
+    tempax = ( tempax * pVBInfo->HT ) /tempbx ;
+
+    return( ( USHORT )tempax ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVCLK2Ptr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetVCLK2Ptr( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
+{
+    USHORT tempbx ;
+
+    USHORT LCDXlat1VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
+    USHORT LCDXlat2VCLK[ 4 ] = { VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 } ;
+    USHORT LVDSXlat1VCLK[ 4 ] = { VCLK40 , VCLK40 , VCLK40 , VCLK40 } ;
+    USHORT LVDSXlat2VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
+    USHORT LVDSXlat3VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
+
+    USHORT CRT2Index , VCLKIndex ;
+    USHORT modeflag , resinfo ;
+    UCHAR *CHTVVCLKPtr = NULL ;
+
+    if ( ModeNo <= 0x13 )
+    {
+        modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;      /* si+St_ResInfo */
+        resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
+        CRT2Index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+    }
+    else
+    {
+        modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;     /* si+Ext_ResInfo */
+        resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+        CRT2Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
+    }
+
+    if ( pVBInfo->IF_DEF_LVDS == 0 )
+    {
+        CRT2Index = CRT2Index >> 6 ;        /*  for LCD */
+        if ( ( ( pVBInfo->VBInfo & SetCRT2ToLCD ) | SetCRT2ToLCDA ) )   /*301b*/
+        {
+            if ( pVBInfo->LCDResInfo != Panel1024x768 )
+            {
+                VCLKIndex = LCDXlat2VCLK[ CRT2Index ] ;
+            }
+            else
+            {
+                 VCLKIndex = LCDXlat1VCLK[ CRT2Index ] ;
+            }
+        }
+        else   /* for TV */
+        {
+            if ( pVBInfo->VBInfo & SetCRT2ToTV )
+            {
+                if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+                {
+                    if ( pVBInfo->SetFlag & RPLLDIV2XO )
+                    {
+                        VCLKIndex = HiTVVCLKDIV2 ;
+
+
+                            VCLKIndex += 25 ;
+
+                    }
+                    else
+                    {
+                        VCLKIndex = HiTVVCLK ;
+
+
+                            VCLKIndex += 25 ;
+
+                    }
+
+                    if ( pVBInfo->SetFlag & TVSimuMode )
+                    {
+                        if( modeflag & Charx8Dot )
+                        {
+                            VCLKIndex = HiTVSimuVCLK ;
+
+
+                                VCLKIndex += 25 ;
+
+                        }
+                        else
+                        {
+                            VCLKIndex = HiTVTextVCLK ;
+
+
+                                VCLKIndex += 25 ;
+
+                        }
+                    }
+
+                    if ( pVBInfo->VBType & VB_XGI301LV )       /* 301lv */
+                    {
+                        if ( !( pVBInfo->VBExtInfo == VB_YPbPr1080i ) )
+                        {
+                            VCLKIndex = YPbPr750pVCLK ;
+                            if ( !( pVBInfo->VBExtInfo == VB_YPbPr750p ) )
+                            {
+                                VCLKIndex = YPbPr525pVCLK ;
+                                if ( !( pVBInfo->VBExtInfo == VB_YPbPr525p ) )
+                                {
+                                    VCLKIndex = YPbPr525iVCLK_2 ;
+                                    if ( !( pVBInfo->SetFlag & RPLLDIV2XO ) )
+                                        VCLKIndex = YPbPr525iVCLK ;
+                                }
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    if ( pVBInfo->VBInfo & SetCRT2ToTV )
+                    {
+                        if ( pVBInfo->SetFlag & RPLLDIV2XO )
+                       {
+                            VCLKIndex = TVVCLKDIV2 ;
+
+
+                            VCLKIndex += 25 ;
+
+                        }
+                        else
+                        {
+                            VCLKIndex = TVVCLK ;
+
+
+                            VCLKIndex += 25 ;
+
+                        }
+                    }
+                }
+            }
+            else
+            {  /* for CRT2 */
+                VCLKIndex = ( UCHAR )XGINew_GetReg2( ( pVBInfo->P3ca + 0x02 ) ) ;      /* Port 3cch */
+               VCLKIndex = ( ( VCLKIndex >> 2 ) & 0x03 ) ;
+                if ( ModeNo > 0x13 )
+                {
+                    VCLKIndex = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;       /* di+Ext_CRTVCLK */
+                    VCLKIndex &= IndexMask ;
+                }
+            }
+        }
+    }
+    else
+    {          /* LVDS */
+        if ( ModeNo <= 0x13 )
+            VCLKIndex = CRT2Index ;
+       else
+           VCLKIndex = CRT2Index ;
+
+        if ( pVBInfo->IF_DEF_CH7005 == 1 )
+        {
+            if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
+            {
+                VCLKIndex &= 0x1f ;
+               tempbx = 0 ;
+
+                if ( pVBInfo->VBInfo & SetPALTV )
+                    tempbx += 2 ;
+
+                if ( pVBInfo->VBInfo & SetCHTVOverScan )
+                    tempbx += 1 ;
+
+                switch( tempbx )
+                {
+                    case 0:
+                        CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC ;
+                        break ;
+                    case 1:
+                        CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC ;
+                        break;
+                    case 2:
+                        CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL ;
+                        break ;
+                    case 3:
+                        CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL ;
+                        break ;
+                    default:
+                        break ;
+                }
+
+                VCLKIndex = CHTVVCLKPtr[ VCLKIndex ] ;
+            }
+        }
+        else
+        {
+            VCLKIndex = VCLKIndex >> 6 ;
+            if ( ( pVBInfo->LCDResInfo == Panel800x600 ) || ( pVBInfo->LCDResInfo == Panel320x480 ) )
+                VCLKIndex = LVDSXlat1VCLK[ VCLKIndex ] ;
+            else if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) )
+                VCLKIndex = LVDSXlat2VCLK[ VCLKIndex ] ;
+            else
+                VCLKIndex = LVDSXlat3VCLK[ VCLKIndex ] ;
+        }
+    }
+    /* VCLKIndex = VCLKIndex&IndexMask ; */
+
+
+
+    return( VCLKIndex ) ;
+}
+
diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
new file mode 100644 (file)
index 0000000..09753d7
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef  _VBSETMODE_
+#define  _VBSETMODE_
+
+extern   void     InitTo330Pointer(UCHAR,PVB_DEVICE_INFO);
+extern   void     XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern   void     XGI_LockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern   void     XGI_LongWait( PVB_DEVICE_INFO );
+extern   void     XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO,  PVB_DEVICE_INFO  );
+extern   void     XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern   void            XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern   void     XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+extern   void     XGI_DisplayOn( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+extern   void     XGI_GetVBType(PVB_DEVICE_INFO);
+extern   void     XGI_SenseCRT1(PVB_DEVICE_INFO );
+extern   void     XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern   void     XGI_GetVBInfo(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern   void     XGI_GetTVInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO );
+extern   void     XGI_SetCRT1Offset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern   void     XGI_SetLCDAGroup(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern   void     XGI_WaitDisply( PVB_DEVICE_INFO );
+extern   USHORT   XGI_GetResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+
+extern   BOOLEAN  XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ) ;
+
+extern   BOOLEAN  XGI_SearchModeID( USHORT ModeNo,USHORT  *ModeIdIndex, PVB_DEVICE_INFO );
+extern   BOOLEAN  XGI_GetLCDInfo(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO );
+extern   BOOLEAN  XGI_BridgeIsOn( PVB_DEVICE_INFO );
+extern   BOOLEAN  XGI_SetCRT2Group301(USHORT ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO);
+extern   USHORT   XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO );
+
+extern   void     XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+extern   void     XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+extern   void     XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+extern   void     XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+extern   void     XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+extern   BOOLEAN  XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+extern   void     XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+extern   USHORT XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo);
+
+#endif
diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
new file mode 100644 (file)
index 0000000..bb25c0e
--- /dev/null
@@ -0,0 +1,534 @@
+#ifndef _VB_STRUCT_
+#define _VB_STRUCT_
+
+#ifdef _INITNEW_
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+
+
+
+typedef struct _XGI_PanelDelayTblStruct
+{
+ UCHAR timer[2];
+} XGI_PanelDelayTblStruct;
+
+typedef struct _XGI_LCDDataStruct
+{
+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} XGI_LCDDataStruct;
+
+
+typedef struct _XGI_LVDSCRT1HDataStruct
+{
+ UCHAR Reg[8];
+} XGI_LVDSCRT1HDataStruct;
+typedef struct _XGI_LVDSCRT1VDataStruct
+{
+ UCHAR Reg[7];
+} XGI_LVDSCRT1VDataStruct;
+
+
+typedef struct _XGI_TVDataStruct
+{
+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT TVHDE;
+ USHORT TVVDE;
+ USHORT RVBHRS;
+ UCHAR FlickerMode;
+ USHORT HALFRVBHRS;
+ UCHAR RY1COE;
+ UCHAR RY2COE;
+ UCHAR RY3COE;
+ UCHAR RY4COE;
+} XGI_TVDataStruct;
+
+typedef struct _XGI_LVDSDataStruct
+{
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} XGI_LVDSDataStruct;
+
+typedef struct _XGI_LVDSDesStruct
+{
+ USHORT LCDHDES;
+ USHORT LCDVDES;
+} XGI_LVDSDesStruct;
+
+typedef struct _XGI_LVDSCRT1DataStruct
+{
+ UCHAR CR[15];
+} XGI_LVDSCRT1DataStruct;
+
+/*add for LCDA*/
+
+
+typedef struct _XGI_StStruct
+{
+ UCHAR St_ModeID;
+ USHORT St_ModeFlag;
+ UCHAR St_StTableIndex;
+ UCHAR St_CRT2CRTC;
+ UCHAR St_CRT2CRTC2;
+ UCHAR St_ResInfo;
+ UCHAR VB_StTVFlickerIndex;
+ UCHAR VB_StTVEdgeIndex;
+ UCHAR VB_StTVYFilterIndex;
+} XGI_StStruct;
+
+typedef struct _XGI_StandTableStruct
+{
+ UCHAR CRT_COLS;
+ UCHAR ROWS;
+ UCHAR CHAR_HEIGHT;
+ USHORT CRT_LEN;
+ UCHAR SR[4];
+ UCHAR MISC;
+ UCHAR CRTC[0x19];
+ UCHAR ATTR[0x14];
+ UCHAR GRC[9];
+} XGI_StandTableStruct;
+
+typedef struct _XGI_ExtStruct
+{
+ UCHAR Ext_ModeID;
+ USHORT Ext_ModeFlag;
+ USHORT Ext_ModeInfo;
+ USHORT Ext_Point;
+ USHORT Ext_VESAID;
+ UCHAR Ext_VESAMEMSize;
+ UCHAR Ext_RESINFO;
+ UCHAR VB_ExtTVFlickerIndex;
+ UCHAR VB_ExtTVEdgeIndex;
+ UCHAR VB_ExtTVYFilterIndex;
+ UCHAR REFindex;
+} XGI_ExtStruct;
+
+typedef struct _XGI_Ext2Struct
+{
+ USHORT Ext_InfoFlag;
+ UCHAR Ext_CRT1CRTC;
+ UCHAR Ext_CRTVCLK;
+ UCHAR Ext_CRT2CRTC;
+ UCHAR Ext_CRT2CRTC2;
+ UCHAR  ModeID;
+ USHORT XRes;
+ USHORT YRes;
+ /* USHORT ROM_OFFSET; */
+} XGI_Ext2Struct;
+
+
+typedef struct _XGI_MCLKDataStruct
+{
+ UCHAR SR28,SR29,SR2A;
+ USHORT CLOCK;
+} XGI_MCLKDataStruct;
+
+typedef struct _XGI_ECLKDataStruct
+{
+ UCHAR SR2E,SR2F,SR30;
+ USHORT CLOCK;
+} XGI_ECLKDataStruct;
+
+typedef struct _XGI_VCLKDataStruct
+{
+ UCHAR SR2B,SR2C;
+ USHORT CLOCK;
+} XGI_VCLKDataStruct;
+
+typedef struct _XGI_VBVCLKDataStruct
+{
+ UCHAR Part4_A,Part4_B;
+ USHORT CLOCK;
+} XGI_VBVCLKDataStruct;
+
+typedef struct _XGI_StResInfoStruct
+{
+ USHORT HTotal;
+ USHORT VTotal;
+} XGI_StResInfoStruct;
+
+typedef struct _XGI_ModeResInfoStruct
+{
+ USHORT HTotal;
+ USHORT VTotal;
+ UCHAR  XChar;
+ UCHAR  YChar;
+} XGI_ModeResInfoStruct;
+
+typedef struct _XGI_LCDNBDesStruct
+{
+  UCHAR NB[12];
+} XGI_LCDNBDesStruct;
+ /*add for new UNIVGABIOS*/
+typedef struct _XGI_LCDDesStruct
+{
+ USHORT LCDHDES;
+ USHORT LCDHRS;
+ USHORT LCDVDES;
+ USHORT LCDVRS;
+} XGI_LCDDesStruct;
+
+typedef struct _XGI_LCDDataTablStruct
+{
+ UCHAR  PANELID;
+ USHORT MASK;
+ USHORT CAP;
+ USHORT DATAPTR;
+} XGI_LCDDataTablStruct;
+
+typedef struct _XGI_TVTablDataStruct
+{
+ USHORT MASK;
+ USHORT CAP;
+ USHORT DATAPTR;
+} XGI_TVDataTablStruct;
+
+typedef struct _XGI330_LCDDesDataStruct
+{
+ USHORT LCDHDES;
+ USHORT LCDHRS;
+ USHORT LCDVDES;
+ USHORT LCDVRS;
+} XGI330_LCDDataDesStruct;
+
+
+typedef struct _XGI330_LVDSDataStruct
+{
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} XGI330_LVDSDataStruct;
+
+typedef struct _XGI330_LCDDesDataStruct2
+{
+ USHORT LCDHDES;
+ USHORT LCDHRS;
+ USHORT LCDVDES;
+ USHORT LCDVRS;
+ USHORT LCDHSync;
+ USHORT LCDVSync;
+} XGI330_LCDDataDesStruct2;
+
+typedef struct _XGI330_LCDDataStruct
+{
+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} XGI330_LCDDataStruct;
+
+
+typedef struct _XGI330_TVDataStruct
+{
+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT TVHDE;
+ USHORT TVVDE;
+ USHORT RVBHRS;
+ UCHAR FlickerMode;
+ USHORT HALFRVBHRS;
+} XGI330_TVDataStruct;
+
+typedef struct _XGI330_LCDDataTablStruct
+{
+ UCHAR  PANELID;
+ USHORT MASK;
+ USHORT CAP;
+ USHORT DATAPTR;
+} XGI330_LCDDataTablStruct;
+
+typedef struct _XGI330_TVDataTablStruct
+{
+ USHORT MASK;
+ USHORT CAP;
+ USHORT DATAPTR;
+} XGI330_TVDataTablStruct;
+
+
+typedef struct _XGI330_CHTVDataStruct
+{
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} XGI330_CHTVDataStruct;
+
+typedef struct _XGI_TimingHStruct
+{
+  UCHAR data[8];
+} XGI_TimingHStruct;
+
+typedef struct _XGI_TimingVStruct
+{
+  UCHAR data[7];
+} XGI_TimingVStruct;
+
+typedef struct _XGI_CH7007TV_TimingHStruct
+{
+  UCHAR data[10];
+} XGI_CH7007TV_TimingHStruct;
+
+typedef struct _XGI_CH7007TV_TimingVStruct
+{
+  UCHAR data[10];
+} XGI_CH7007TV_TimingVStruct;
+
+typedef struct _XGI_XG21CRT1Struct
+{
+ UCHAR ModeID,CR02,CR03,CR15,CR16;
+} XGI_XG21CRT1Struct;
+
+typedef struct _XGI330_CHTVRegDataStruct
+{
+ UCHAR Reg[16];
+} XGI330_CHTVRegDataStruct;
+
+typedef struct _XGI330_LCDCapStruct
+{
+               UCHAR      LCD_ID;
+                USHORT     LCD_Capability;
+                UCHAR      LCD_SetFlag;
+                UCHAR      LCD_DelayCompensation;
+                UCHAR      LCD_HSyncWidth;
+                UCHAR      LCD_VSyncWidth;
+                UCHAR      LCD_VCLK;
+                UCHAR      LCDA_VCLKData1;
+                UCHAR      LCDA_VCLKData2;
+                UCHAR      LCUCHAR_VCLKData1;
+                UCHAR      LCUCHAR_VCLKData2;
+                UCHAR      PSC_S1;
+                UCHAR      PSC_S2;
+                UCHAR      PSC_S3;
+                UCHAR      PSC_S4;
+                UCHAR      PSC_S5;
+                UCHAR      PWD_2B;
+                UCHAR      PWD_2C;
+                UCHAR      PWD_2D;
+                UCHAR      PWD_2E;
+                UCHAR      PWD_2F;
+                UCHAR      Spectrum_31;
+                UCHAR      Spectrum_32;
+                UCHAR      Spectrum_33;
+                UCHAR      Spectrum_34;
+} XGI330_LCDCapStruct;
+
+typedef struct _XGI21_LVDSCapStruct
+{
+                USHORT     LVDS_Capability;
+                USHORT     LVDSHT;
+                USHORT     LVDSVT;
+                USHORT     LVDSHDE;
+                USHORT     LVDSVDE;
+                USHORT     LVDSHFP;
+                USHORT     LVDSVFP;
+                USHORT     LVDSHSYNC;
+                USHORT     LVDSVSYNC;
+                UCHAR      VCLKData1;
+                UCHAR      VCLKData2;
+                UCHAR      PSC_S1;
+                UCHAR      PSC_S2;
+                UCHAR      PSC_S3;
+                UCHAR      PSC_S4;
+                UCHAR      PSC_S5;
+} XGI21_LVDSCapStruct;
+
+typedef struct _XGI_CRT1TableStruct
+{
+  UCHAR CR[16];
+} XGI_CRT1TableStruct;
+
+
+typedef struct _XGI330_VCLKDataStruct
+{
+    UCHAR SR2B,SR2C;
+    USHORT CLOCK;
+} XGI330_VCLKDataStruct;
+
+typedef struct _XGI301C_Tap4TimingStruct
+{
+    USHORT DE;
+    UCHAR  Reg[64];   /* C0-FF */
+} XGI301C_Tap4TimingStruct;
+
+typedef struct _XGI_New_StandTableStruct
+{
+       UCHAR  CRT_COLS;
+       UCHAR  ROWS;
+       UCHAR  CHAR_HEIGHT;
+       USHORT CRT_LEN;
+       UCHAR  SR[4];
+       UCHAR  MISC;
+       UCHAR  CRTC[0x19];
+       UCHAR  ATTR[0x14];
+       UCHAR  GRC[9];
+} XGI_New_StandTableStruct;
+
+typedef UCHAR DRAM8Type[8];
+typedef UCHAR DRAM4Type[4];
+typedef UCHAR DRAM32Type[32];
+typedef UCHAR DRAM2Type[2];
+
+typedef struct _VB_DEVICE_INFO  VB_DEVICE_INFO;
+typedef VB_DEVICE_INFO *       PVB_DEVICE_INFO;
+
+struct _VB_DEVICE_INFO
+{
+    BOOLEAN  ISXPDOS;
+    ULONG   P3c4,P3d4,P3c0,P3ce,P3c2,P3cc;
+    ULONG   P3ca,P3c6,P3c7,P3c8,P3c9,P3da;
+    ULONG   Part0Port,Part1Port,Part2Port;
+    ULONG   Part3Port,Part4Port,Part5Port;
+    USHORT   RVBHCFACT,RVBHCMAX,RVBHRS;
+    USHORT   VGAVT,VGAHT,VGAVDE,VGAHDE;
+    USHORT   VT,HT,VDE,HDE;
+    USHORT   LCDHRS,LCDVRS,LCDHDES,LCDVDES;
+
+    USHORT   ModeType;
+    USHORT   IF_DEF_LVDS,IF_DEF_TRUMPION,IF_DEF_DSTN;/* ,IF_DEF_FSTN; add for dstn */
+    USHORT   IF_DEF_CRT2Monitor,IF_DEF_VideoCapture;
+    USHORT   IF_DEF_LCDA,IF_DEF_CH7017,IF_DEF_YPbPr,IF_DEF_ScaleLCD,IF_DEF_OEMUtil,IF_DEF_PWD;
+    USHORT   IF_DEF_ExpLink;
+    USHORT   IF_DEF_CH7005,IF_DEF_HiVision;
+    USHORT   IF_DEF_CH7007; /* Billy 2007/05/03 */
+    USHORT   LCDResInfo,LCDTypeInfo, VBType;/*301b*/
+    USHORT   VBInfo,TVInfo,LCDInfo, Set_VGAType;
+    USHORT   VBExtInfo;/*301lv*/
+    USHORT   SetFlag;
+    USHORT   NewFlickerMode;
+    USHORT   SelectCRT2Rate;
+
+    PUCHAR ROMAddr;
+    PUCHAR FBAddr;
+    ULONG BaseAddr;
+    ULONG RelIO;
+
+    DRAM4Type  *CR6B;
+    DRAM4Type  *CR6E;
+    DRAM32Type *CR6F;
+    DRAM2Type  *CR89;
+
+    DRAM8Type  *SR15; /* pointer : point to array */
+    DRAM8Type  *CR40;
+    UCHAR  *pSoftSetting;
+    UCHAR  *pOutputSelect;
+
+    USHORT *pRGBSenseData;
+    USHORT *pRGBSenseData2; /*301b*/
+    USHORT *pVideoSenseData;
+    USHORT *pVideoSenseData2;
+    USHORT *pYCSenseData;
+    USHORT *pYCSenseData2;
+
+    UCHAR  *pSR07;
+    UCHAR  *CR49;
+    UCHAR  *pSR1F;
+    UCHAR  *AGPReg;
+    UCHAR  *SR16;
+    UCHAR  *pSR21;
+    UCHAR  *pSR22;
+    UCHAR  *pSR23;
+    UCHAR  *pSR24;
+    UCHAR  *SR25;
+    UCHAR  *pSR31;
+    UCHAR  *pSR32;
+    UCHAR  *pSR33;
+    UCHAR  *pSR36;      /* alan 12/07/2006 */
+    UCHAR  *pCRCF;
+    UCHAR  *pCRD0;      /* alan 12/07/2006 */
+    UCHAR  *pCRDE;      /* alan 12/07/2006 */
+    UCHAR  *pCR8F;      /* alan 12/07/2006 */
+    UCHAR  *pSR40;      /* alan 12/07/2006 */
+    UCHAR  *pSR41;      /* alan 12/07/2006 */
+    UCHAR  *pDVOSetting;
+    UCHAR  *pCR2E;
+    UCHAR  *pCR2F;
+    UCHAR  *pCR46;
+    UCHAR  *pCR47;
+    UCHAR  *pCRT2Data_1_2;
+    UCHAR  *pCRT2Data_4_D;
+    UCHAR  *pCRT2Data_4_E;
+    UCHAR  *pCRT2Data_4_10;
+    XGI_MCLKDataStruct  *MCLKData;
+    XGI_ECLKDataStruct  *ECLKData;
+
+    UCHAR   *XGI_TVDelayList;
+    UCHAR   *XGI_TVDelayList2;
+    UCHAR   *CHTVVCLKUNTSC;
+    UCHAR   *CHTVVCLKONTSC;
+    UCHAR   *CHTVVCLKUPAL;
+    UCHAR   *CHTVVCLKOPAL;
+    UCHAR   *NTSCTiming;
+    UCHAR   *PALTiming;
+    UCHAR   *HiTVExtTiming;
+    UCHAR   *HiTVSt1Timing;
+    UCHAR   *HiTVSt2Timing;
+    UCHAR   *HiTVTextTiming;
+    UCHAR   *YPbPr750pTiming;
+    UCHAR   *YPbPr525pTiming;
+    UCHAR   *YPbPr525iTiming;
+    UCHAR   *HiTVGroup3Data;
+    UCHAR   *HiTVGroup3Simu;
+    UCHAR   *HiTVGroup3Text;
+    UCHAR   *Ren525pGroup3;
+    UCHAR   *Ren750pGroup3;
+    UCHAR   *ScreenOffset;
+    UCHAR   *pXGINew_DRAMTypeDefinition;
+    UCHAR   *pXGINew_I2CDefinition ;
+    UCHAR   *pXGINew_CR97 ;
+
+    XGI330_LCDCapStruct  *LCDCapList;
+    XGI21_LVDSCapStruct  *XG21_LVDSCapList;
+
+    XGI_TimingHStruct  *TimingH;
+    XGI_TimingVStruct  *TimingV;
+
+    XGI_StStruct          *SModeIDTable;
+    XGI_StandTableStruct  *StandTable;
+    XGI_ExtStruct         *EModeIDTable;
+    XGI_Ext2Struct        *RefIndex;
+    /* XGINew_CRT1TableStruct *CRT1Table; */
+    XGI_CRT1TableStruct    *XGINEWUB_CRT1Table;
+    XGI_VCLKDataStruct    *VCLKData;
+    XGI_VBVCLKDataStruct  *VBVCLKData;
+    XGI_StResInfoStruct   *StResInfo;
+    XGI_ModeResInfoStruct *ModeResInfo;
+    XGI_XG21CRT1Struct   *UpdateCRT1;
+};  /* _VB_DEVICE_INFO */
+
+
+typedef struct
+{
+    USHORT    Horizontal_ACTIVE;
+    USHORT    Horizontal_FP;
+    USHORT    Horizontal_SYNC;
+    USHORT    Horizontal_BP;
+    USHORT    Vertical_ACTIVE;
+    USHORT    Vertical_FP;
+    USHORT    Vertical_SYNC;
+    USHORT    Vertical_BP;
+    double    DCLK;
+    UCHAR     FrameRate;
+    UCHAR     Interlace;
+    USHORT    Margin;
+} TimingInfo;
+
+#define _VB_STRUCT_
+#endif /* _VB_STRUCT_ */
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
new file mode 100644 (file)
index 0000000..781caef
--- /dev/null
@@ -0,0 +1,4406 @@
+#define  Tap4
+
+
+XGI_MCLKDataStruct XGI330New_MCLKData[]=
+{
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166},
+ { 0x7C,0x08,0x80,200},
+ { 0x79,0x06,0x80,250},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300}
+};
+//yilin modify for xgi20
+XGI_MCLKDataStruct XGI340New_MCLKData[]=
+{
+ { 0x16,0x01,0x01,166},
+ { 0x19,0x02,0x01,124},
+ { 0x7C,0x08,0x01,200},
+ { 0x79,0x06,0x01,250},
+ { 0x29,0x01,0x81,301},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166}
+};
+
+XGI_MCLKDataStruct XGI27New_MCLKData[]=
+{
+ { 0x5c,0x23,0x01,166},
+ { 0x19,0x02,0x01,124},
+ { 0x7C,0x08,0x80,200},
+ { 0x79,0x06,0x80,250},
+ { 0x29,0x01,0x81,300},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166}
+};
+
+XGI_ECLKDataStruct XGI330_ECLKData[]=
+{
+ { 0x7c,0x08,0x01,200},
+ { 0x7c,0x08,0x01,200},
+ { 0x7C,0x08,0x80,200},
+ { 0x79,0x06,0x80,250},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300}
+};
+//yilin modify for xgi20
+XGI_ECLKDataStruct XGI340_ECLKData[]=
+{
+ { 0x5c,0x23,0x01,166},
+ { 0x55,0x84,0x01,123},
+ { 0x7C,0x08,0x01,200},
+ { 0x79,0x06,0x01,250},
+ { 0x29,0x01,0x81,301},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166}
+};
+
+
+
+UCHAR XGI340_SR13[4][8]={
+{0x35,0x45,0xb1,0x00,0x00,0x00,0x00,0x00},/* SR13 */
+{0x41,0x51,0x5c,0x00,0x00,0x00,0x00,0x00},/* SR14 */
+{0x31,0x42,0x42,0x00,0x00,0x00,0x00,0x00},/* SR18 */
+{0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00}/* SR1B */
+};
+
+UCHAR XGI340_cr41[24][8]=
+{{0x20,0x50,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
+{0xc4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
+{0xc4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */
+{0xb5,0xa4,0xa4,0x00,0x00,0x00,0x00,0x00},
+{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},
+{0x90,0x90,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */
+{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */
+{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */
+{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */
+{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */
+{0x88,0xa8,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */
+{0x44,0x44,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */
+{0x48,0x48,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */
+{0x54,0x54,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */
+{0x54,0x54,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */
+{0x0a,0x0a,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */
+{0x44,0x44,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */
+{0x10,0x10,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */
+{0x11,0x11,0x0a,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */
+{0x05,0x05,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */
+{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */
+{0x05,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
+};
+
+
+UCHAR XGI27_cr41[24][8]=
+{
+{0x20,0x40,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
+{0xC4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
+{0xC4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */
+{0xB5,0x13,0xa4,0x00,0x00,0x00,0x00,0x00},/* 3 CR40[7],CR99[2:0],CR45[3:0]*/
+{0xf0,0xf5,0xf0,0x00,0x00,0x00,0x00,0x00},/* 4 CR59 */
+{0x90,0x90,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */
+{0x77,0x67,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */
+{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */
+{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */
+{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */
+{0x88,0xcc,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */
+{0x44,0x88,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */
+{0x48,0x88,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */
+{0x54,0x32,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */
+{0x54,0x33,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */
+{0x0a,0x07,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */
+{0x44,0x63,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */
+{0x10,0x14,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */
+{0x11,0x0B,0x0C,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */
+{0x05,0x22,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */
+{0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */
+{0x05,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
+};
+
+
+#if 0
+UCHAR XGI27_cr41[24][8]=
+{
+{0x20,0x60,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
+{0x04,0x44,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
+{0x04,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */
+{0xb5,0x03,0xa4,0x00,0x00,0x00,0x00,0x00},/* 3 CR40[7],CR99[2:0],CR45[3:0]*/
+{0xf0,0xf5,0xf0,0x00,0x00,0x00,0x00,0x00},/* 4 CR59 */
+{0xa4,0x1C,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */
+{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */
+{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */
+{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */
+{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */
+{0x48,0xa8,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */
+{0x77,0x88,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */
+{0x88,0x88,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */
+{0x44,0x32,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */
+{0x44,0x33,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */
+{0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */
+{0x44,0x63,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */
+{0x0A,0x14,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */
+{0x0C,0x0B,0x0C,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */
+{0x05,0x22,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */
+{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */
+{0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
+};
+#endif
+UCHAR XGI340_CR6B[8][4]={
+{0xaa,0xaa,0xaa,0xaa},
+{0xaa,0xaa,0xaa,0xaa},
+{0xaa,0xaa,0xaa,0xaa},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00}
+};
+
+UCHAR XGI340_CR6E[8][4]={
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00}
+};
+
+UCHAR XGI340_CR6F[8][32]={
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+UCHAR XGI340_CR89[8][2]={
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00}
+};
+                        /* CR47,CR48,CR49,CR4A,CR4B,CR4C,CR70,CR71,CR74,CR75,CR76,CR77 */
+UCHAR XGI340_AGPReg[12]={0x28,0x23,0x00,0x20,0x00,0x20,0x00,0x05,0xd0,0x10,0x10,0x00};
+
+UCHAR XGI340_SR16[4]={0x03,0x83,0x03,0x83};
+
+UCHAR XGI330_SR15_1[8][8]={
+{0x0,0x0,0x00,0x00,0x20,0x20,0x00,0x00},
+{0x5,0x15,0x15,0x15,0x15,0x15,0x00,0x00},
+{0xba,0xba,0xba,0xba,0xBA,0xBA,0x00,0x00},
+{0x55,0x57,0x57,0xAB,0xAB,0xAB,0x00,0x00},
+{0x60,0x34,0x34,0x34,0x34,0x34,0x00,0x00},
+{0x0,0x80,0x80,0x80,0x83,0x83,0x00,0x00},
+{0x50,0x50,0x50,0x3C,0x3C,0x3C,0x00,0x00},
+{0x0,0xa5,0xfb,0xf6,0xF6,0xF6,0x00,0x00}
+};
+
+UCHAR XGI330_cr40_1[15][8]={
+{0x66,0x40,0x40,0x28,0x24,0x24,0x00,0x00},
+{0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00},
+{0x00,0xf0,0xf0,0xf0,0xF0,0xF0,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x10,0x10,0x10,0x10,0x20,0x20,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x88,0x88,0x88,0xAA,0xAC,0xAC,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x77,0x77,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0xA2,0x00,0x00,0xA2,0xA2,0x00,0x00},
+};
+
+UCHAR XGI330_sr25[]={0x00,0x0};
+UCHAR XGI330_sr31=0xc0;
+UCHAR XGI330_sr32=0x11;
+UCHAR XGI330_SR33=0x00;
+UCHAR XG40_CRCF=0x13;
+UCHAR XG40_DRAMTypeDefinition=0xFF ;
+
+XGI_StStruct XGI330_SModeIDTable[]=
+{
+ {0x01,0x9208,0x01,0x00,0x10,0x00,0x00,0x01,0x00},
+ {0x01,0x1210,0x14,0x01,0x00,0x01,0x00,0x01,0x00},
+ {0x01,0x1010,0x17,0x02,0x11,0x00,0x00,0x01,0x01},
+ {0x03,0x8208,0x03,0x00,0x14,0x00,0x00,0x01,0x02},
+ {0x03,0x0210,0x16,0x01,0x04,0x01,0x00,0x01,0x02},
+ {0x03,0x0010,0x18,0x02,0x15,0x00,0x00,0x01,0x03},
+ {0x05,0x9209,0x05,0x00,0x10,0x00,0x00,0x00,0x04},
+ {0x06,0x8209,0x06,0x00,0x14,0x00,0x00,0x00,0x05},
+ {0x07,0x0000,0x07,0x03,0x05,0x03,0x00,0x01,0x03},
+ {0x07,0x0000,0x19,0x02,0x15,0x02,0x00,0x01,0x03},
+ {0x0d,0x920a,0x0d,0x00,0x10,0x00,0x00,0x00,0x04},
+ {0x0e,0x820a,0x0e,0x00,0x14,0x00,0x00,0x00,0x05},
+ {0x0f,0x0202,0x11,0x01,0x04,0x01,0x00,0x00,0x05},
+ {0x10,0x0212,0x12,0x01,0x04,0x01,0x00,0x00,0x05},
+ {0x11,0x0212,0x1a,0x04,0x24,0x04,0x00,0x00,0x05},
+ {0x12,0x0212,0x1b,0x04,0x24,0x04,0x00,0x00,0x05},
+ {0x13,0x021b,0x1c,0x00,0x14,0x00,0x00,0x00,0x04},
+ {0x12,0x0010,0x18,0x02,0x24,0x02,0x00,0x00,0x05},/* St_CRT2CRTC2 not sure */
+ {0x12,0x0210,0x18,0x01,0x24,0x01,0x00,0x00,0x05},/* St_CRT2CRTC2 not sure */
+ {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+
+XGI_ExtStruct  XGI330_EModeIDTable[]=
+{
+ {0x6a,0x2212,0x0407,0x3a81,0x0102,0x08,0x07,0x00,0x00,0x07,0x0e},
+ {0x2e,0x0a1b,0x0306,0x3a57,0x0101,0x08,0x06,0x00,0x00,0x05,0x06},
+ {0x2f,0x0a1b,0x0305,0x3a50,0x0100,0x08,0x05,0x00,0x00,0x05,0x05},
+ {0x30,0x2a1b,0x0407,0x3a81,0x0103,0x08,0x07,0x00,0x00,0x07,0x0e},
+ {0x31,0x0a1b,0x030d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d},
+ {0x32,0x0a1b,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e},
+ {0x33,0x0a1d,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d},
+ {0x34,0x2a1d,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e},
+ {0x35,0x0a1f,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d},
+ {0x36,0x2a1f,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e},
+ {0x37,0x0212,0x0508,0x3aab,0x0104,0x08,0x08,0x00,0x00,0x00,0x16},
+ {0x38,0x0a1b,0x0508,0x3aab,0x0105,0x08,0x08,0x00,0x00,0x00,0x16},
+ {0x3a,0x0e3b,0x0609,0x3adc,0x0107,0x08,0x09,0x00,0x00,0x00,0x1e},
+ {0x3c,0x0e3b,0x070a,0x3af2,0x0130,0x08,0x0a,0x00,0x00,0x00,0x22},     /* mode 1600x1200 add CRT2MODE [2003/10/07] */
+ {0x3d,0x0e7d,0x070a,0x3af2,0x0131,0x08,0x0a,0x00,0x00,0x00,0x22},     /* mode 1600x1200 add CRT2MODE */
+ {0x40,0x9a1c,0x0000,0x3a34,0x010d,0x08,0x00,0x00,0x00,0x04,0x00},
+ {0x41,0x9a1d,0x0000,0x3a34,0x010e,0x08,0x00,0x00,0x00,0x04,0x00},     /* ModeIdIndex = 0x10 */
+ {0x43,0x0a1c,0x0306,0x3a57,0x0110,0x08,0x06,0x00,0x00,0x05,0x06},
+ {0x44,0x0a1d,0x0306,0x3a57,0x0111,0x08,0x06,0x00,0x00,0x05,0x06},
+ {0x46,0x2a1c,0x0407,0x3a81,0x0113,0x08,0x07,0x00,0x00,0x07,0x0e},
+ {0x47,0x2a1d,0x0407,0x3a81,0x0114,0x08,0x07,0x00,0x00,0x07,0x0e},
+ {0x49,0x0a3c,0x0508,0x3aab,0x0116,0x08,0x08,0x00,0x00,0x00,0x16},
+ {0x4a,0x0a3d,0x0508,0x3aab,0x0117,0x08,0x08,0x00,0x00,0x00,0x16},
+ {0x4c,0x0e7c,0x0609,0x3adc,0x0119,0x08,0x09,0x00,0x00,0x00,0x1e},
+ {0x4d,0x0e7d,0x0609,0x3adc,0x011a,0x08,0x09,0x00,0x00,0x00,0x1e},
+ {0x50,0x9a1b,0x0001,0x3a3b,0x0132,0x08,0x01,0x00,0x00,0x04,0x02},
+ {0x51,0xba1b,0x0103,0x3a42,0x0133,0x08,0x03,0x00,0x00,0x07,0x03},
+ {0x52,0x9a1b,0x0204,0x3a49,0x0134,0x08,0x04,0x00,0x00,0x00,0x04},
+ {0x56,0x9a1d,0x0001,0x3a3b,0x0135,0x08,0x01,0x00,0x00,0x04,0x02},
+ {0x57,0xba1d,0x0103,0x3a42,0x0136,0x08,0x03,0x00,0x00,0x07,0x03},
+ {0x58,0x9a1d,0x0204,0x3a49,0x0137,0x08,0x04,0x00,0x00,0x00,0x04},
+ {0x59,0x9a1b,0x0000,0x3a34,0x0138,0x08,0x00,0x00,0x00,0x04,0x00},
+ {0x5A,0x021b,0x0014,0x3b83,0x0138,0x08,0x01,0x00,0x00,0x04,0x3f},     /* ModeIdIndex = 0x20 */
+ {0x5B,0x0a1d,0x0014,0x3b83,0x0135,0x08,0x01,0x00,0x00,0x04,0x3f},
+ {0x5d,0x0a1d,0x0305,0x3a50,0x0139,0x08,0x05,0x00,0x00,0x07,0x05},
+ {0x62,0x0a3f,0x0306,0x3a57,0x013a,0x08,0x06,0x00,0x00,0x05,0x06},
+ {0x63,0x2a3f,0x0407,0x3a81,0x013b,0x08,0x07,0x00,0x00,0x07,0x0e},
+ {0x64,0x0a7f,0x0508,0x3aab,0x013c,0x08,0x08,0x00,0x00,0x00,0x16},
+ {0x65,0x0eff,0x0609,0x3adc,0x013d,0x08,0x09,0x00,0x00,0x00,0x1e},
+ {0x66,0x0eff,0x070a,0x3af2,0x013e,0x08,0x0a,0x00,0x00,0x00,0x22},     /* mode 1600x1200 add CRT2MODE */
+ {0x68,0x067b,0x080b,0x3b17,0x013f,0x08,0x0b,0x00,0x00,0x00,0x29},
+ {0x69,0x06fd,0x080b,0x3b17,0x0140,0x08,0x0b,0x00,0x00,0x00,0x29},
+ {0x6b,0x07ff,0x080b,0x3b17,0x0141,0x10,0x0b,0x00,0x00,0x00,0x29},
+ {0x6c,0x067b,0x090c,0x3b37,0x0000,0x08,0x0c,0x00,0x00,0x00,0x2f},
+ {0x6d,0x06fd,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f},
+ {0x6e,0x07ff,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f},
+ {0x70,0x2a1b,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34},
+ {0x71,0x0a1b,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37},
+ {0x74,0x0a1d,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37},     /* ModeIdIndex = 0x30 */
+ {0x75,0x0a3d,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a},
+ {0x76,0x2a1f,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34},
+ {0x77,0x0a1f,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37},
+ {0x78,0x0a3f,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a},
+ {0x79,0x0a3b,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a},
+ {0x7a,0x2a1d,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34},
+ {0x7b,0x0e3b,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d},
+ {0x7c,0x0e7d,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d},
+ {0x7d,0x0eff,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d},
+ {0x20,0x0e3b,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43},
+ {0x21,0x0e7d,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43},
+ {0x22,0x0eff,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43},
+ {0x23,0x0e3b,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41},
+ {0x24,0x0e7d,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41},
+ {0x25,0x0eff,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41},
+ {0x26,0x063b,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42},     /* ModeIdIndex = 0x40 */
+ {0x27,0x067d,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42},
+ {0x28,0x06ff,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42},
+ {0xff,0x0000,0x0000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+XGI_StandTableStruct XGI330_StandTable[]=
+{
+/* MD_0_200 */
+ {
+  0x28,0x18,0x08,0x0800,
+  {0x09,0x03,0x00,0x02},
+  0x63,
+  {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* MD_1_200 */
+ {
+  0x28,0x18,0x08,0x0800,
+  {0x09,0x03,0x00,0x02},
+  0x63,
+  {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* MD_2_200 */
+ {
+  0x50,0x18,0x08,0x1000,
+  {0x01,0x03,0x00,0x02},
+  0x63,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* MD_3_200 */
+ {
+  0x50,0x18,0x08,0x1000,
+  {0x01,0x03,0x00,0x02},
+  0x63,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* MD_4 */
+ {
+  0x28,0x18,0x08,0x4000,
+  {0x09,0x03,0x00,0x02},
+  0x63,
+  {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+   0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
+   0xff},
+  {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x01,0x00,0x03,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
+   0xff}
+ },
+/* MD_5 */
+ {
+  0x28,0x18,0x08,0x4000,
+  {0x09,0x03,0x00,0x02},
+  0x63,
+  {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+   0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
+   0xff},
+  {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x01,0x00,0x03,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
+   0xff}
+ },
+/* MD_6 */
+ {
+  0x50,0x18,0x08,0x4000,
+  {0x01,0x01,0x00,0x06},
+  0x63,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,
+   0xff},
+  {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+   0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+   0x01,0x00,0x01,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,
+   0xff}
+ },
+/* MD_7 */
+ {
+  0x50,0x18,0x0e,0x1000,
+  {0x00,0x03,0x00,0x03},
+  0xa6,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+   0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3,
+   0xff},
+  {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+   0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+   0x0e,0x00,0x0f,0x08},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
+   0xff}
+ },
+/* MDA_DAC */
+ {
+  0x00,0x00,0x00,0x0000,
+  {0x00,0x00,0x00,0x15},
+  0x15,
+  {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+   0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f,
+   0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00,
+   0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15,
+   0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+   0x15,0x15,0x15,0x15},
+  {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+   0x3f}
+ },
+/* CGA_DAC */
+ {
+  0x00,0x10,0x04,0x0114,
+  {0x11,0x09,0x15,0x00},
+  0x10,
+  {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,
+   0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a,
+   0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10,
+   0x04},
+  {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04,
+   0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e,
+   0x3e,0x2b,0x3b,0x2f},
+  {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
+   0x3f}
+ },
+/* EGA_DAC */
+ {
+  0x00,0x10,0x04,0x0114,
+  {0x11,0x05,0x15,0x20},
+  0x30,
+  {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18,
+   0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38,
+   0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12,
+   0x06},
+  {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26,
+   0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e,
+   0x1e,0x0b,0x1b,0x0f},
+  {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
+   0x3f}
+ },
+/* VGA_DAC */
+ {
+  0x00,0x10,0x04,0x0114,
+  {0x11,0x09,0x15,0x2a},
+  0x3a,
+  {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05,
+   0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20,
+   0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10,
+   0x1f},
+  {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d,
+   0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15,
+   0x1c,0x0e,0x11,0x15},
+  {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00,
+   0x04}
+ },
+ {
+  0x08,0x0c,0x10,0x0a08,
+  {0x0c,0x0e,0x10,0x0b},
+  0x0c,
+  {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00,
+   0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00,
+   0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00,
+   0x06},
+  {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08,
+   0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00,
+   0x00,0x00,0x00,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x00}
+ },
+/* MD_D */
+ {
+  0x28,0x18,0x08,0x2000,
+  {0x09,0x0f,0x00,0x06},
+  0x63,
+  {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+   0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x01,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+   0xff}
+ },
+/* MD_E */
+ {
+  0x50,0x18,0x08,0x4000,
+  {0x01,0x0f,0x00,0x06},
+  0x63,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x01,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+   0xff}
+ },
+/* ExtVGATable */
+ {
+  0x00,0x00,0x00,0x0000,
+  {0x01,0x0f,0x00,0x0e},
+  0x23,
+  {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+   0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+   0x01,0x00,0x00,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+   0xff}
+ },
+/* ROM_SAVEPTR */
+ {
+  0x9f,0x3b,0x00,0x00c0,
+  {0x00,0x00,0x00,0x00},
+  0x00,
+  {0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x3f,
+   0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x00,0x00,0x1a,0x00,0xac,0x3e,0x00,0xc0,
+   0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x00,0x00,0x00,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x00}
+ },
+/* MD_F */
+ {
+  0x50,0x18,0x0e,0x8000,
+  {0x01,0x0f,0x00,0x06},
+  0xa2,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,
+   0xff},
+  {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
+   0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
+   0x0b,0x00,0x05,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,
+   0xff}
+ },
+/* MD_10 */
+ {
+  0x50,0x18,0x0e,0x8000,
+  {0x01,0x0f,0x00,0x06},
+  0xa3,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x01,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+   0xff}
+ },
+/* MD_0_350 */
+ {
+  0x28,0x18,0x0e,0x0800,
+  {0x09,0x03,0x00,0x02},
+  0xa3,
+  {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,
+   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+   0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* MD_1_350 */
+ {
+  0x28,0x18,0x0e,0x0800,
+  {0x09,0x03,0x00,0x02},
+  0xa3,
+  {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+   0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* MD_2_350 */
+ {
+  0x50,0x18,0x0e,0x1000,
+  {0x01,0x03,0x00,0x02},
+  0xa3,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+   0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* MD_3_350 */
+ {
+  0x50,0x18,0x0e,0x1000,
+  {0x01,0x03,0x00,0x02},
+  0xa3,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+   0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* MD_0_1_400 */
+ {
+  0x28,0x18,0x10,0x0800,
+  {0x08,0x03,0x00,0x02},
+  0x67,
+  {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,
+   0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x0c,0x00,0x0f,0x08},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* MD_2_3_400 */
+ {
+  0x50,0x18,0x10,0x1000,
+  {0x00,0x03,0x00,0x02},
+  0x67,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x0c,0x00,0x0f,0x08},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* MD_7_400 */
+ {
+  0x50,0x18,0x10,0x1000,
+  {0x00,0x03,0x00,0x02},
+  0x66,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+   0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+   0x0e,0x00,0x0f,0x08},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
+   0xff}
+ },
+/* MD_11 */
+ {
+  0x50,0x1d,0x10,0xa000,
+  {0x01,0x0f,0x00,0x06},
+  0xe3,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
+   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+   0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xc3,
+   0xff},
+  {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+   0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+   0x01,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,
+   0xff}
+ },
+/* ExtEGATable */
+ {
+  0x50,0x1d,0x10,0xa000,
+  {0x01,0x0f,0x00,0x06},
+  0xe3,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
+   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+   0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x01,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+   0xff}
+ },
+/* MD_13 */
+ {
+  0x28,0x18,0x08,0x2000,
+  {0x01,0x0f,0x00,0x0e},
+  0x63,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+   0x41,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+   0xff}
+ }
+};
+
+XGI_TimingHStruct XGI_TimingH[]=
+{{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}};
+
+XGI_TimingVStruct XGI_TimingV[]=
+{{{0x00,0x00,0x00,0x00,0x00,0x00,0x00}}};
+
+XGI_XG21CRT1Struct XGI_UpdateCRT1Table[]=
+{
+ {0x01,0x27,0x91,0x8f,0xc0},   /* 00 */
+ {0x03,0x4f,0x83,0x8f,0xc0},   /* 01 */
+ {0x05,0x27,0x91,0x8f,0xc0},   /* 02 */
+ {0x06,0x4f,0x83,0x8f,0xc0},   /* 03 */
+ {0x07,0x4f,0x83,0x8f,0xc0},   /* 04 */
+ {0x0d,0x27,0x91,0x8f,0xc0},   /* 05 */
+ {0x0e,0x4f,0x83,0x8f,0xc0},   /* 06 */
+ {0x0f,0x4f,0x83,0x5d,0xc0},   /* 07 */
+ {0x10,0x4f,0x83,0x5d,0xc0},   /* 08 */
+ {0x11,0x4f,0x83,0xdf,0x0c},   /* 09 */
+ {0x12,0x4f,0x83,0xdf,0x0c},   /* 10 */
+ {0x13,0x4f,0x83,0x8f,0xc0},   /* 11 */
+ {0x2e,0x4f,0x83,0xdf,0x0c},   /* 12 */
+ {0x2e,0x4f,0x87,0xdf,0xc0},   /* 13 */
+ {0x2f,0x4f,0x83,0x8f,0xc0},   /* 14 */
+ {0x50,0x27,0x91,0xdf,0x0c},   /* 15 */
+ {0x59,0x27,0x91,0x8f,0xc0}    /* 16 */
+};
+
+XGI_CRT1TableStruct XGI_CRT1Table[]=
+{
+ {{0x2d,0x28,0x90,0x2c,0x90,0x00,0x04,0x00,
+    0xbf,0x1f,0x9c,0x8e,0x96,0xb9,0x30}}, /* 0x0 */
+ {{0x2d,0x28,0x90,0x2c,0x90,0x00,0x04,0x00,
+    0x0b,0x3e,0xe9,0x8b,0xe7,0x04,0x00}}, /* 0x1 */
+ {{0x3D,0x31,0x81,0x37,0x1F,0x00,0x05,0x00,
+    0x72,0xF0,0x58,0x8C,0x57,0x73,0xA0}}, /* 0x2 */
+ {{0x4F,0x3F,0x93,0x45,0x0D,0x00,0x01,0x00,
+    0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x3 */
+ {{0x5F,0x50,0x82,0x55,0x81,0x00,0x05,0x00,
+    0xBF,0x1F,0x9C,0x8E,0x96,0xB9,0x30}}, /* 0x4 */
+ {{0x5F,0x50,0x82,0x55,0x81,0x00,0x05,0x00,
+    0x0B,0x3E,0xE9,0x8B,0xE7,0x04,0x00}}, /* 0x5 */
+ {{0x63,0x50,0x86,0x56,0x9B,0x00,0x01,0x00,
+    0x06,0x3E,0xE8,0x8B,0xE7,0xFF,0x10}}, /* 0x6 */
+ {{0x64,0x4F,0x88,0x55,0x9D,0x00,0x01,0x00,
+    0xF2,0x1F,0xE0,0x83,0xDF,0xF3,0x10}}, /* 0x7 */
+ {{0x63,0x4F,0x87,0x5A,0x81,0x00,0x05,0x00,
+    0xFB,0x1F,0xE0,0x83,0xDF,0xFC,0x10}}, /* 0x8 */
+ {{0x65,0x4F,0x89,0x58,0x80,0x00,0x05,0x60,
+    0xFB,0x1F,0xE0,0x83,0xDF,0xFC,0x80}}, /* 0x9 */
+ {{0x65,0x4F,0x89,0x58,0x80,0x00,0x05,0x60,
+    0x01,0x3E,0xE0,0x83,0xDF,0x02,0x80}}, /* 0xa */
+ {{0x67,0x4F,0x8B,0x58,0x81,0x00,0x05,0x60,
+    0x0D,0x3E,0xE0,0x83,0xDF,0x0E,0x90}}, /* 0xb */
+ {{0x65,0x4F,0x89,0x57,0x9F,0x00,0x01,0x00,
+   0xFB,0x1F,0xE6,0x8A,0xDF,0xFC,0x10}}, /* 0xc */
+ {{0x7B,0x63,0x9F,0x6A,0x93,0x00,0x05,0x00,    /* ; 0D (800x600,56Hz) */
+    0x6F,0xF0,0x58,0x8A,0x57,0x70,0xA0}},         /* ; (VCLK 36.0MHz) */
+ {{0x7F,0x63,0x83,0x6C,0x1C,0x00,0x06,0x00,    /* ; 0E (800x600,60Hz) */
+    0x72,0xF0,0x58,0x8C,0x57,0x73,0xA0}},         /* ; (VCLK 40.0MHz) */
+ {{0x7D,0x63,0x81,0x6E,0x1D,0x00,0x06,0x00,    /* ; 0F (800x600,72Hz) */
+    0x98,0xF0,0x7C,0x82,0x57,0x99,0x80}},         /* ; (VCLK 50.0MHz) */
+ {{0x7F,0x63,0x83,0x69,0x13,0x00,0x06,0x00,    /* ; 10 (800x600,75Hz) */
+    0x6F,0xF0,0x58,0x8B,0x57,0x70,0xA0}},         /* ; (VCLK 49.5MHz) */
+ {{0x7E,0x63,0x82,0x6B,0x13,0x00,0x06,0x00,    /* ; 11 (800x600,85Hz) */
+    0x75,0xF0,0x58,0x8B,0x57,0x76,0xA0}},         /* ; (VCLK 56.25MHz) */
+ {{0x81,0x63,0x85,0x6D,0x18,0x00,0x06,0x60,    /* ; 12 (800x600,100Hz) */
+    0x7A,0xF0,0x58,0x8B,0x57,0x7B,0xA0}},         /* ; (VCLK 75.8MHz) */
+ {{0x83,0x63,0x87,0x6E,0x19,0x00,0x06,0x60,    /* ; 13 (800x600,120Hz) */
+    0x81,0xF0,0x58,0x8B,0x57,0x82,0xA0}},         /* ; (VCLK 79.411MHz) */
+ {{0x85,0x63,0x89,0x6F,0x1A,0x00,0x06,0x60,    /* ; 14 (800x600,160Hz) */
+   0x91,0xF0,0x58,0x8B,0x57,0x92,0xA0}},         /* ; (VCLK 105.822MHz) */
+ {{0x99,0x7F,0x9D,0x84,0x1A,0x00,0x02,0x00,
+    0x96,0x1F,0x7F,0x83,0x7F,0x97,0x10}}, /* 0x15 */
+ {{0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00,
+    0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x16 */
+ {{0xA1,0x7F,0x85,0x86,0x97,0x00,0x02,0x00,
+    0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x17 */
+ {{0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00,
+    0x1E,0xF5,0x00,0x83,0xFF,0x1F,0x90}}, /* 0x18 */
+ {{0xA7,0x7F,0x8B,0x89,0x95,0x00,0x02,0x00,
+    0x26,0xF5,0x00,0x83,0xFF,0x27,0x90}}, /* 0x19 */
+ {{0xA9,0x7F,0x8D,0x8C,0x9A,0x00,0x02,0x62,
+    0x2C,0xF5,0x00,0x83,0xFF,0x2D,0x14}}, /* 0x1a */
+ {{0xAB,0x7F,0x8F,0x8D,0x9B,0x00,0x02,0x62,
+    0x35,0xF5,0x00,0x83,0xFF,0x36,0x14}}, /* 0x1b */
+ {{0xCF,0x9F,0x93,0xB2,0x01,0x00,0x03,0x00,
+    0x14,0xBA,0x00,0x83,0xFF,0x15,0x00}}, /* 0x1c */
+ {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00,
+    0x28,0x5A,0x00,0x83,0xFF,0x29,0x89}}, /* 0x1d */
+ {{0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00,
+    0x28,0x5A,0x00,0x83,0xFF,0x29,0x89}}, /* 0x1e */
+ {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x00,
+    0x2E,0x5A,0x00,0x83,0xFF,0x2F,0x89}}, /* 0x1f */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+    0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x20 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+    0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x21 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+    0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x22 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+    0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x23 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+    0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x24 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+    0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x25 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+    0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x26 */
+ {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
+    0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x27 */
+ {{0x43,0xEF,0x87,0x06,0x00,0x41,0x05,0x62,
+    0xD4,0x1F,0xA0,0x83,0x9F,0xD5,0x9F}}, /* 0x28 */
+ {{0x45,0xEF,0x89,0x07,0x01,0x41,0x05,0x62,
+    0xD9,0x1F,0xA0,0x83,0x9F,0xDA,0x9F}}, /* 0x29 */
+ {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
+    0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2a */
+ {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
+    0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2b */
+ {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
+    0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2c */
+ {{0x59,0xFF,0x9D,0x17,0x13,0x41,0x05,0x44,
+    0x33,0xBA,0x00,0x83,0xFF,0x34,0x0F}}, /* 0x2d */
+ {{0x5B,0xFF,0x9F,0x18,0x14,0x41,0x05,0x44,
+    0x38,0xBA,0x00,0x83,0xFF,0x39,0x0F}}, /* 0x2e */
+ {{0x5B,0xFF,0x9F,0x18,0x14,0x41,0x05,0x44,
+    0x3D,0xBA,0x00,0x83,0xFF,0x3E,0x0F}}, /* 0x2f */
+ {{0x5D,0xFF,0x81,0x19,0x95,0x41,0x05,0x44,
+    0x41,0xBA,0x00,0x84,0xFF,0x42,0x0F}}, /* 0x30 */
+ {{0x55,0xFF,0x99,0x0D,0x0C,0x41,0x05,0x00,
+    0x3E,0xBA,0x00,0x84,0xFF,0x3F,0x0F}}, /* 0x31 */
+ {{0x7F,0x63,0x83,0x6C,0x1C,0x00,0x06,0x00,
+    0x72,0xBA,0x27,0x8B,0xDF,0x73,0x80}}, /* 0x32 */
+ {{0x7F,0x63,0x83,0x69,0x13,0x00,0x06,0x00,
+    0x6F,0xBA,0x26,0x89,0xDF,0x6F,0x80}}, /* 0x33 */
+ {{0x7F,0x63,0x82,0x6B,0x13,0x00,0x06,0x00,
+    0x75,0xBA,0x29,0x8C,0xDF,0x75,0x80}}, /* 0x34 */
+ {{0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00,
+    0x24,0xF1,0xAF,0x85,0x3F,0x25,0xB0}}, /* 0x35 */
+ {{0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00,
+    0x1E,0xF1,0xAD,0x81,0x3F,0x1F,0xB0}}, /* 0x36 */
+ {{0xA7,0x7F,0x88,0x89,0x15,0x00,0x02,0x00,
+    0x26,0xF1,0xB1,0x85,0x3F,0x27,0xB0}}, /* 0x37 */
+ {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00,
+    0x28,0xC4,0x7A,0x8E,0xCF,0x29,0xA1}}, /* 0x38 */
+ {{0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00,
+    0x28,0xD4,0x7A,0x8E,0xCF,0x29,0xA1}}, /* 0x39 */
+ {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x00,
+    0x2E,0xD4,0x7D,0x81,0xCF,0x2F,0xA1}}, /* 0x3a */
+ {{0xDC,0x9F,0x00,0xAB,0x19,0x00,0x07,0x00,
+    0xE6,0xEF,0xC0,0xC3,0xBF,0xE7,0x90}}, /* 0x3b */
+ {{0x6B,0x59,0x8F,0x5E,0x8C,0x00,0x05,0x00,
+    0x0B,0x3E,0xE9,0x8B,0xE7,0x04,0x00}}, /* 0x3c */
+ {{0x7B,0x63,0x9F,0x6A,0x93,0x00,0x05,0x00,
+    0x6F,0xF0,0x58,0x8A,0x57,0x70,0xA0}}, /* 0x3d */
+ {{0x86,0x6A,0x8a,0x74,0x06,0x00,0x02,0x00,
+    0x8c,0x15,0x4f,0x83,0xef,0x8d,0x30}}, /* 0x3e */
+ {{0x81,0x6A,0x85,0x70,0x00,0x00,0x02,0x00,
+    0x0f,0x3e,0xeb,0x8e,0xdf,0x10,0x00}}, /* 0x3f */
+ {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00,
+    0x20,0xF5,0x03,0x88,0xFF,0x21,0x90}}, /* 0x40 */
+ {{0xE6,0xAE,0x8A,0xBD,0x90,0x00,0x03,0x00,
+    0x3D,0x10,0x1A,0x8D,0x19,0x3E,0x2F}}, /* 0x41 */
+ {{0xB9,0x8F,0x9D,0x9B,0x8A,0x00,0x06,0x00,
+    0x7D,0xFF,0x60,0x83,0x5F,0x7E,0x90}}, /* 0x42 */
+ {{0xC3,0x8F,0x87,0x9B,0x0B,0x00,0x07,0x00,
+    0x82,0xFF,0x60,0x83,0x5F,0x83,0x90}},  /* 0x43 */
+ {{0xAD,0x7F,0x91,0x8E,0x9C,0x00,0x02,0x82,
+    0x49,0xF5,0x00,0x83,0xFF,0x4A,0x90}},  /* 0x44 */
+ {{0xCD,0x9F,0x91,0xA7,0x19,0x00,0x07,0x60,
+    0xE6,0xFF,0xC0,0x83,0xBF,0xE7,0x90}},  /* 0x45 */
+ {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x60,
+    0xF1,0xFF,0xC0,0x83,0xBF,0xF2,0x90}},  /* 0x46 */
+ {{0xD7,0x9F,0x9B,0xAC,0x1E,0x00,0x07,0x00,
+    0x03,0xDE,0xC0,0x84,0xBF,0x04,0x90}}  /* 0x47 */
+};
+
+XGI330_CHTVRegDataStruct XGI_CHTVRegUNTSC[] = {
+                /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
+                {{      0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 00 (640x200,640x400) */
+                {{      0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 01 (640x350) */
+                {{      0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 02 (720x400) */
+                {{      0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 03 (720x350) */
+                {{      0x6A,0x77,0xBB,0x6E,0x84,0x2E,0x02,0x5A,0x04,0x00,0x80,0x20,0x7E,0x80,0x97,0x00  }},/* 04 (640x480) ;;5/6/02 */
+                {{      0xCF,0x77,0xB7,0xC8,0x84,0x3B,0x02,0x5A,0x04,0x00,0x80,0x19,0x88,0xAE,0xA3,0x00  }},/* 05 (800x600) ;;1/12/02 */
+                {{      0xEE,0x77,0xBB,0x66,0x87,0x32,0x01,0x5A,0x04,0x00,0x80,0x1B,0xD4,0x2F,0x6F,0x00  }}/* 06 (1024x768) ;;5/6/02 */
+          };
+
+XGI330_CHTVRegDataStruct XGI_CHTVRegONTSC[]= {
+                /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
+                {{      0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 00 (640x200,640x400) */
+                {{      0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 01 (640x350) */
+                {{      0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 02 (720x400) */
+                {{      0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 03 (720x350) */
+                {{      0x69,0x77,0xBB,0x6E,0x84,0x1E,0x00,0x5A,0x04,0x00,0x80,0x25,0x1A,0x80,0x26,0x00  }},/* 04 (640x480) ;;5/6/02 */
+                {{      0xCE,0x77,0xB7,0xB6,0x83,0x2C,0x02,0x5A,0x04,0x00,0x80,0x1C,0x00,0x82,0x97,0x00  }},/* 05 (800x600) ;;5/6/02 */
+                {{      0xED,0x77,0xBB,0x66,0x8C,0x21,0x02,0x5A,0x04,0x00,0x80,0x1F,0xA0,0x7E,0x73,0x00  }}/* 06 (1024x768) ;;5/6/02 */
+          };
+
+XGI330_CHTVRegDataStruct XGI_CHTVRegUPAL[]=  {
+                /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
+                {{      0x41,0x7F,0xB7,0x34,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* ; 00 (640x200,640x400) */
+                {{      0x41,0x7F,0xB7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* ; 01 (640x350) */
+                {{      0x41,0x7F,0xB7,0x34,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* ; 02 (720x400) */
+                {{      0x41,0x7F,0xB7,0x12,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* ; 03 (720x350) */
+                {{      0x61,0x7F,0xB7,0x99,0x84,0x35,0x04,0x5A,0x05,0x00,0x80,0x26,0x2A,0x55,0x5D,0x00  }},/* ; 04 (640x480) */
+                {{      0xC3,0x7F,0xB7,0x7A,0x84,0x40,0x02,0x5A,0x05,0x00,0x80,0x1F,0x84,0x3D,0x28,0x00  }},/* ; 05 (800x600) ;;1/12/02 */
+                {{      0xE5,0x7F,0xB7,0x1D,0xA7,0x3E,0x04,0x5A,0x05,0x00,0x80,0x20,0x3E,0xE4,0x22,0x00  }}/* ; 06 (1024x768) ;;1/12/02 */
+         };
+
+XGI330_CHTVRegDataStruct XGI_CHTVRegOPAL[]={
+                /* Index:000,0x01,0x02,0x04,0x03,0x05,0x06,0x07,0x08,0x15,0x1F,0x0C,0x0D,0x0E,0x0F,0x10h */
+                {{      0x41,0x7F,0xB7,0x36,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 00 (640x200,640x400) */
+                {{      0x41,0x7F,0xB7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 01 (640x350) */
+                {{      0x41,0x7F,0xB7,0x36,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 02 (720x400) */
+                {{      0x41,0x7F,0xB7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 03 (720x350) */
+                {{      0x61,0x7F,0xB7,0x99,0x84,0x35,0x04,0x5A,0x05,0x00,0x80,0x26,0x2A,0x55,0x5D,0x00 }},/* 04 (640x480) */
+                {{      0xC1,0x7F,0xB7,0x4D,0x8C,0x1E,0x31,0x5A,0x05,0x00,0x80,0x26,0x78,0x19,0x34,0x00 }},/* 05 (800x600) ;;1/12/02 */
+                {{      0xE4,0x7F,0xB7,0x1E,0xAF,0x29,0x37,0x5A,0x05,0x00,0x80,0x25,0x8C,0xB2,0x2A,0x00 }}/* 06 (1024x768) ;;1/12/02 */
+            };
+
+UCHAR XGI_CH7017LV1024x768[]={0x60,0x02,0x00,0x07,0x40,0xED,0xA3,
+                                       0xC8,0xC7,0xAC,0xE0,0x02};
+UCHAR XGI_CH7017LV1400x1050[]={0x60,0x03,0x11,0x00,0x40,0xE3,0xAD,
+                                       0xDB,0xF6,0xAC,0xE0,0x02};
+
+
+/*add for new UNIVGABIOS*/
+XGI330_LCDDataStruct  XGI_StLCD1024x768Data[]=
+{
+ {   62,  25, 800, 546,1344, 806},
+ {   32,  15, 930, 546,1344, 806},
+ {   62,  25, 800, 546,1344, 806}, /* chiawen for dot9 -> dot8 */
+ {  104,  45, 945, 496,1344, 806},
+ {   62,  25, 800, 546,1344, 806},
+ {   31,  18,1008, 624,1344, 806},
+ {    1,   1,1344, 806,1344, 806}
+};
+
+XGI330_LCDDataStruct  XGI_ExtLCD1024x768Data[]=
+{
+ {   42,  25,1536, 419,1344, 806}, /* { 12, 5, 896, 512,1344, 806}, // alan 09/12/2003 */
+ {   48,  25,1536, 369,1344, 806}, /* { 12, 5, 896, 510,1344, 806}, // alan 09/12/2003 */
+ {   42,  25,1536, 419,1344, 806}, /* { 32, 15,1008, 505,1344, 806}, // alan 09/12/2003 */
+ {   48,  25,1536, 369,1344, 806}, /* { 32, 15,1008, 514,1344, 806}, // alan 09/12/2003 */
+ {   12,   5, 896, 500,1344, 806},
+ {   42,  25,1024, 625,1344, 806},
+ {    1,   1,1344, 806,1344, 806},
+ {   12,   5, 896, 500,1344, 806},
+ {   42,  25,1024, 625,1344, 806},
+ {    1,   1,1344, 806,1344, 806},
+ {   12,   5, 896, 500,1344, 806},
+ {   42,  25,1024, 625,1344, 806},
+ {    1,   1,1344, 806,1344, 806}
+};
+
+/*XGI330_LCDDataStruct  XGI_St2LCD1024x768Data[]=
+{
+ {   62,  25, 800, 546,1344, 806},
+ {   32,  15, 930, 546,1344, 806},
+ {   62,  25, 800, 546,1344, 806},
+ {  104,  45, 945, 496,1344, 806},
+ {   62,  25, 800, 546,1344, 806},
+ {   31,  18,1008, 624,1344, 806},
+ {    1,   1,1344, 806,1344, 806}
+};*/
+
+XGI330_LCDDataStruct  XGI_CetLCD1024x768Data[]=
+{
+       {         1,1,1344,806,1344,806           }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {         1,1,1344,806,1344,806           }, /* 01 (320x350,640x350) */
+        {         1,1,1344,806,1344,806           }, /* 02 (360x400,720x400) */
+        {         1,1,1344,806,1344,806           }, /* 03 (720x350) */
+        {         1,1,1344,806,1344,806           }, /* 04 (640x480x60Hz) */
+        {         1,1,1344,806,1344,806           }, /* 05 (800x600x60Hz) */
+        {         1,1,1344,806,1344,806           }  /* 06 (1024x768x60Hz) */
+};
+
+XGI330_LCDDataStruct  XGI_StLCD1280x1024Data[]=
+{
+ {   22,   5, 800, 510,1650,1088},
+ {   22,   5, 800, 510,1650,1088},
+ {  176,  45, 900, 510,1650,1088},
+ {  176,  45, 900, 510,1650,1088},
+ {   22,   5, 800, 510,1650,1088},
+ {   13,   5,1024, 675,1560,1152},
+ {   16,   9,1266, 804,1688,1072},
+ {    1,   1,1688,1066,1688,1066}
+};
+
+XGI330_LCDDataStruct  XGI_ExtLCD1280x1024Data[]=
+{
+ {  211,  60,1024, 501,1688,1066},
+ {  211,  60,1024, 508,1688,1066},
+ {  211,  60,1024, 501,1688,1066},
+ {  211,  60,1024, 508,1688,1066},
+ {  211,  60,1024, 500,1688,1066},
+ {  211,  75,1024, 625,1688,1066},
+ {  211, 120,1280, 798,1688,1066},
+ {    1,   1,1688,1066,1688,1066}
+};
+
+XGI330_LCDDataStruct  XGI_St2LCD1280x1024Data[]=
+{
+ {   22,   5, 800, 510,1650,1088},
+ {   22,   5, 800, 510,1650,1088},
+ {  176,  45, 900, 510,1650,1088},
+ {  176,  45, 900, 510,1650,1088},
+ {   22,   5, 800, 510,1650,1088},
+ {   13,   5,1024, 675,1560,1152},
+ {   16,   9,1266, 804,1688,1072},
+ {    1,   1,1688,1066,1688,1066}
+};
+
+XGI330_LCDDataStruct  XGI_CetLCD1280x1024Data[]=
+{
+       {         1,1,1688,1066,1688,1066         }, /* 00 (320x200,320x400,640x200,640x400) */
+        {         1,1,1688,1066,1688,1066         }, /* 01 (320x350,640x350) */
+        {         1,1,1688,1066,1688,1066         }, /* 02 (360x400,720x400) */
+        {         1,1,1688,1066,1688,1066         }, /* 03 (720x350) */
+        {         1,1,1688,1066,1688,1066         }, /* 04 (640x480x60Hz) */
+        {         1,1,1688,1066,1688,1066         }, /* 05 (800x600x60Hz) */
+        {         1,1,1688,1066,1688,1066         }, /* 06 (1024x768x60Hz) */
+        {         1,1,1688,1066,1688,1066         }, /* 07 (1280x1024x60Hz) */
+        {         1,1,1688,1066,1688,1066         } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataStruct  XGI_StLCD1400x1050Data[]=
+{
+       {         211,100,2100,408,1688,1066      }, /* 00 (320x200,320x400,640x200,640x400) */
+        {         211,64,1536,358,1688,1066       }, /* 01 (320x350,640x350) */
+        {         211,100,2100,408,1688,1066      }, /* 02 (360x400,720x400) */
+        {         211,64,1536,358,1688,1066       }, /* 03 (720x350) */
+        {         211,48,840,488,1688,1066        }, /* 04 (640x480x60Hz) */
+        {         211,72,1008,609,1688,1066       }, /* 05 (800x600x60Hz) */
+        {         211,128,1400,776,1688,1066      }, /* 06 (1024x768x60Hz) */
+        {         1,1,1688,1066,1688,1066         }, /* 07 (1280x1024x60Hz w/o Scaling) */
+        {         1,1,1688,1066,1688,1066         }  /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataStruct  XGI_ExtLCD1400x1050Data[]=
+{
+       {         211,100,2100,408,1688,1066      }, /* 00 (320x200,320x400,640x200,640x400) */
+        {         211,64,1536,358,1688,1066       }, /* 01 (320x350,640x350) */
+        {         211,100,2100,408,1688,1066      }, /* 02 (360x400,720x400) */
+        {         211,64,1536,358,1688,1066       }, /* 03 (720x350) */
+        {         211,48,840,488,1688,1066        }, /* 04 (640x480x60Hz) */
+        {         211,72,1008,609,1688,1066       }, /* 05 (800x600x60Hz) */
+        {         211,128,1400,776,1688,1066      }, /* 06 (1024x768x60Hz) */
+        {         1,1,1688,1066,1688,1066         }, /* 07 (1280x1024x60Hz w/o Scaling) */
+        {         1,1,1688,1066,1688,1066         }  /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataStruct  XGI_ExtLCD1600x1200Data[]=
+{
+        {         4,1,1620,420,2160,1250          }, /* { 3,1,2160,425,2160,1250 }, // 00 (320x200,320x400,640x200,640x400) // alan 10/14/2003 */
+        {         27,7,1920,375,2160,1250         }, /* 01 (320x350,640x350) */
+        {         4,1,1620,420,2160,1250          }, /* { 3,1,2160,425,2160,1250 }, // 02 (360x400,720x400) // alan 10/14/2003 */
+        {         27,7,1920,375,2160,1250         }, /* 03 (720x350) */
+        {         27,4,800,500,2160,1250          }, /* 04 (640x480x60Hz) */
+        {         4,1,1080,625,2160,1250          }, /* 05 (800x600x60Hz) */
+        {         5,2,1350,800,2160,1250          }, /* 06 (1024x768x60Hz) */
+        {         27,16,1500,1064,2160,1250       }, /* 07 (1280x1024x60Hz) */
+        {         9,7,1920,1106,2160,1250         }, /* 08 (1400x1050x60Hz) */
+        {         1,1,2160,1250,2160,1250         }  /* 09 (1600x1200x60Hz) ;302lv */
+};
+
+XGI330_LCDDataStruct  XGI_StLCD1600x1200Data[]=
+{
+        {         27,4,800,500,2160,1250          },/* 00 (320x200,320x400,640x200,640x400) */
+        {         27,4,800,500,2160,1250          },/* 01 (320x350,640x350) */
+        {         27,4,800,500,2160,1250          },/* 02 (360x400,720x400) */
+        {         27,4,800,500,2160,1250          },/* 03 (720x350) */
+        {         27,4,800,500,2160,1250          },/* 04 (320x240,640x480) */
+        {         4,1,1080,625,2160,1250          },/* 05 (400x300,800x600) */
+        {         5,2,1350,800,2160,1250          },/* 06 (512x384,1024x768) */
+        {         135,88,1600,1100,2160,1250      },/* 07 (1280x1024) */
+        {         1,1,1800,1500,2160,1250         },/* 08 (1400x1050) */
+        {         1,1,2160,1250,2160,1250         } /* 09 (1600x1200) */
+};
+
+XGI330_LCDDataStruct  XGI_CetLCD1400x1050Data[]=
+{
+       {         1,1,1688,1066,1688,1066         }, /* 00 (320x200,320x400,640x200,640x400) */
+        {         1,1,1688,1066,1688,1066         }, /* 01 (320x350,640x350) */
+        {         1,1,1688,1066,1688,1066         }, /* 02 (360x400,720x400) */
+        {         1,1,1688,1066,1688,1066         }, /* 03 (720x350) */
+        {         1,1,1688,1066,1688,1066         }, /* 04 (640x480x60Hz) */
+        {         1,1,1688,1066,1688,1066         }, /* 05 (800x600x60Hz) */
+        {         1,1,1688,1066,1688,1066         }, /* 06 (1024x768x60Hz) */
+        {         1,1,1688,1066,1688,1066         }, /* 07 (1280x1024x60Hz) */
+        {         1,1,1688,1066,1688,1066         }  /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataStruct  XGI_NoScalingData[]=
+{
+ {    1,   1, 800, 449, 800, 449},
+ {    1,   1, 800, 449, 800, 449},
+ {    1,   1, 900, 449, 900, 449},
+ {    1,   1, 900, 449, 900, 449},
+ {    1,   1, 800, 525, 800, 525},
+ {    1,   1,1056, 628,1056, 628},
+ {    1,   1,1344, 806,1344, 806},
+ {    1,   1,1688,1066,1688,1066}
+};
+
+XGI330_LCDDataStruct  XGI_ExtLCD1024x768x75Data[]=
+{
+        {42,25,1536,419,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {48,25,1536,369,1344,806 }, /* ; 01 (320x350,640x350) */
+        {42,25,1536,419,1344,806 }, /* ; 02 (360x400,720x400) */
+        {48,25,1536,369,1344,806 }, /* ; 03 (720x350) */
+        {8,5,1312,500,1312,800   }, /* ; 04 (640x480x75Hz) */
+        {41,25,1024,625,1312,800 }, /* ; 05 (800x600x75Hz) */
+        {1,1,1312,800,1312,800   }  /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataStruct  XGI_StLCD1024x768x75Data[]=
+{
+        {42,25,1536,419,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {48,25,1536,369,1344,806 }, /* ; 01 (320x350,640x350) */
+        {42,25,1536,419,1344,806 }, /* ; 02 (360x400,720x400) */
+        {48,25,1536,369,1344,806 }, /* ; 03 (720x350) */
+        {8,5,1312,500,1312,800   }, /* ; 04 (640x480x75Hz) */
+        {41,25,1024,625,1312,800 }, /* ; 05 (800x600x75Hz) */
+        {1,1,1312,800,1312,800   }  /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataStruct  XGI_CetLCD1024x768x75Data[]=
+{
+        {1,1,1312,800,1312,800}, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {1,1,1312,800,1312,800}, /* ; 01 (320x350,640x350) */
+        {1,1,1312,800,1312,800}, /* ; 02 (360x400,720x400) */
+        {1,1,1312,800,1312,800}, /* ; 03 (720x350) */
+        {1,1,1312,800,1312,800}, /* ; 04 (640x480x75Hz) */
+        {1,1,1312,800,1312,800}, /* ; 05 (800x600x75Hz) */
+        {1,1,1312,800,1312,800} /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataStruct  XGI_ExtLCD1280x1024x75Data[]=
+{
+        {211,60,1024,501,1688,1066   }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {211,60,1024,508,1688,1066   }, /* ; 01 (320x350,640x350) */
+        {211,60,1024,501,1688,1066   }, /* ; 02 (360x400,720x400) */
+        {211,60,1024,508,1688,1066   }, /* ; 03 (720x350) */
+        {211,45,768,498,1688,1066    }, /* ; 04 (640x480x75Hz) */
+        {211,75,1024,625,1688,1066   }, /* ; 05 (800x600x75Hz) */
+        {211,120,1280,798,1688,1066  }, /* ; 06 (1024x768x75Hz) */
+        {1,1,1688,1066,1688,1066     }  /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataStruct  XGI_StLCD1280x1024x75Data[]=
+{
+        {211,60,1024,501,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {211,60,1024,508,1688,1066 }, /* ; 01 (320x350,640x350) */
+        {211,60,1024,501,1688,1066 }, /* ; 02 (360x400,720x400) */
+        {211,60,1024,508,1688,1066 }, /* ; 03 (720x350) */
+        {211,45,768,498,1688,1066  }, /* ; 04 (640x480x75Hz) */
+        {211,75,1024,625,1688,1066 }, /* ; 05 (800x600x75Hz) */
+        {211,120,1280,798,1688,1066}, /* ; 06 (1024x768x75Hz) */
+        {1,1,1688,1066,1688,1066   }  /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataStruct  XGI_CetLCD1280x1024x75Data[]=
+{
+        {1,1,1688,1066,1688,1066}, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {1,1,1688,1066,1688,1066}, /* ; 01 (320x350,640x350) */
+        {1,1,1688,1066,1688,1066}, /* ; 02 (360x400,720x400) */
+        {1,1,1688,1066,1688,1066}, /* ; 03 (720x350) */
+        {1,1,1688,1066,1688,1066}, /* ; 04 (640x480x75Hz) */
+        {1,1,1688,1066,1688,1066}, /* ; 05 (800x600x75Hz) */
+        {1,1,1688,1066,1688,1066}, /* ; 06 (1024x768x75Hz) */
+        {1,1,1688,1066,1688,1066}  /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataStruct  XGI_NoScalingDatax75[]=
+{
+        {1,1,800,449,800,449    }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {1,1,800,449,800,449    }, /* ; 01 (320x350,640x350) */
+        {1,1,900,449,900,449    }, /* ; 02 (360x400,720x400) */
+        {1,1,900,449,900,449    }, /* ; 03 (720x350) */
+        {1,1,840,500,840,500    }, /* ; 04 (640x480x75Hz) */
+        {1,1,1056,625,1056,625  }, /* ; 05 (800x600x75Hz) */
+        {1,1,1312,800,1312,800  }, /* ; 06 (1024x768x75Hz) */
+        {1,1,1688,1066,1688,1066}, /* ; 07 (1280x1024x75Hz) */
+        {1,1,1688,1066,1688,1066}, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */
+        {1,1,2160,1250,2160,1250}, /* ; 09 (1600x1200x75Hz) */
+        {1,1,1688,806,1688,806  }  /* ; 0A (1280x768x75Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_ExtLCDDes1024x768Data[]=
+{
+   {  9,1057,0, 771  }, /* ; 00 (320x200,320x400,640x200,640x400) */
+   {  9,1057,0, 771  }, /* ; 01 (320x350,640x350) */
+   {  9,1057,0, 771  }, /* ; 02 (360x400,720x400) */
+   {  9,1057,0, 771  }, /* ; 03 (720x350) */
+   {  9,1057,0, 771  }, /* ; 04 (640x480x60Hz) */
+   {  9,1057,0, 771  }, /* ; 05 (800x600x60Hz) */
+   {  9,1057,805, 770  }  /* ; 06 (1024x768x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_StLCDDes1024x768Data[]=
+{
+        { 9,1057,737,703   }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        { 9,1057,686,651   }, /* ; 01 (320x350,640x350) */
+        { 9,1057,737,703   }, /* ; 02 (360x400,720x400) */
+        { 9,1057,686,651   }, /* ; 03 (720x350) */
+        { 9,1057,776,741   }, /* ; 04 (640x480x60Hz) */
+        { 9,1057, 0 ,771   }, /* ; 05 (800x600x60Hz) */
+        { 9,1057,805,770   }  /* ; 06 (1024x768x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_CetLCDDes1024x768Data[]=
+{
+               {      1152,856,622,587   }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {      1152,856,597,562   }, /* ; 01 (320x350,640x350) */
+        {      1152,856,622,587   }, /* ; 02 (360x400,720x400) */
+        {      1152,856,597,562   }, /* ; 03 (720x350) */
+        {      1152,856,662,627   }, /* ; 04 (640x480x60Hz) */
+        {      1232,936,722,687   }, /* ; 05 (800x600x60Hz) */
+        {      0,1048,805,770   }  /* ; 06 (1024x768x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024Data[]=
+{
+        {      18,1346,981,940     },/* 00 (320x200,320x400,640x200,640x400) */
+        {      18,1346,926,865     },/* 01 (320x350,640x350) */
+        {      18,1346,981,940     },/* 02 (360x400,720x400) */
+        {      18,1346,926,865     },/* 03 (720x350) */
+        {      18,1346,0,1025     },/* 04 (640x480x60Hz) */
+        {      18,1346,0,1025     },/* 05 (800x600x60Hz) */
+        {      18,1346,1065,1024     },/* 06 (1024x768x60Hz) */
+        {      18,1346,1065,1024     }/* 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024Data[]=
+{
+        {      18,1346,970,907     },/* 00 (320x200,320x400,640x200,640x400) */
+        {      18,1346,917,854     },/* 01 (320x350,640x350) */
+        {      18,1346,970,907     },/* 02 (360x400,720x400) */
+        {      18,1346,917,854     },/* 03 (720x350) */
+        {      18,1346,0,1025     },/* 04 (640x480x60Hz) */
+        {      18,1346,0,1025     },/* 05 (800x600x60Hz) */
+        {      18,1346,1065,1024     },/* 06 (1024x768x60Hz) */
+        {      18,1346,1065,1024     }/* 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_CetLCDDLDes1280x1024Data[]=
+{
+        {      1368,1008,752,711    }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      1368,1008,729,688    }, /* 01 (320x350,640x350) */
+        {      1368,1008,752,711    }, /* 02 (360x400,720x400) */
+       {      1368,1008,729,688    }, /* 03 (720x350) */
+        {      1368,1008,794,753    }, /* 04 (640x480x60Hz) */
+        {      1448,1068,854,813    }, /* 05 (800x600x60Hz) */
+        {      1560,1200,938,897    }, /* 06 (1024x768x60Hz) */
+        {      18,1346,1065,1024    }  /* 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_ExtLCDDes1280x1024Data[]=
+{
+        {      9,1337,981,940    }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {      9,1337,926,884    }, /* ; 01 (320x350,640x350) alan, 2003/09/30 */
+        {      9,1337,981,940    }, /* ; 02 (360x400,720x400) */
+        {      9,1337,926,884    }, /* ; 03 (720x350) alan, 2003/09/30 */
+        {      9,1337,0,1025    }, /* ; 04 (640x480x60Hz) */
+        {      9,1337,0,1025    }, /* ; 05 (800x600x60Hz) */
+        {      9,1337,1065,1024    }, /* ; 06 (1024x768x60Hz) */
+        {      9,1337,1065,1024    }  /* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_StLCDDes1280x1024Data[]=
+{
+        {      9,1337,970,907    }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {      9,1337,917,854    }, /* ; 01 (320x350,640x350) */
+        {      9,1337,970,907    }, /* ; 02 (360x400,720x400) */
+        {      9,1337,917,854    }, /* ; 03 (720x350) */
+        {      9,1337,0,1025    }, /* ; 04 (640x480x60Hz) */
+        {      9,1337,0,1025    }, /* ; 05 (800x600x60Hz) */
+        {      9,1337,1065,1024    }, /* ; 06 (1024x768x60Hz) */
+        {      9,1337,1065,1024    }  /* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_CetLCDDes1280x1024Data[]=
+{
+        {      1368,1008,752,711    }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      1368,1008,729,688    }, /* 01 (320x350,640x350) */
+        {      1368,1008,752,711    }, /* 02 (360x400,720x400) */
+       {      1368,1008,729,688    }, /* 03 (720x350) */
+        {      1368,1008,794,753    }, /* 04 (640x480x60Hz) */
+        {      1448,1068,854,813    }, /* 05 (800x600x60Hz) */
+        {      1560,1200,938,897    }, /* 06 (1024x768x60Hz) */
+        {      9,1337,1065,1024    }  /* 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_StLCDDLDes1400x1050Data[]=
+{
+        {      18,1464,0,1051    }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      18,1464,0,1051    }, /* 01 (320x350,640x350) */
+        {      18,1464,0,1051    }, /* 02 (360x400,720x400) */
+        {      18,1464,0,1051    }, /* 03 (720x350) */
+        {      18,1464,0,1051    }, /* 04 (640x480x60Hz) */
+        {      18,1464,0,1051    }, /* 05 (800x600x60Hz) */
+        {      18,1464,0,1051    }, /* 06 (1024x768x60Hz) */
+        {      1646,1406,1053,1038    }, /* 07 (1280x1024x60Hz) */
+        {      18,1464,0,1051    }  /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1400x1050Data[]=
+{
+        {      18,1464,0,1051    }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      18,1464,0,1051    }, /* 01 (320x350,640x350) */
+        {      18,1464,0,1051    }, /* 02 (360x400,720x400) */
+        {      18,1464,0,1051    }, /* 03 (720x350) */
+        {      18,1464,0,1051    }, /* 04 (640x480x60Hz) */
+        {      18,1464,0,1051    }, /* 05 (800x600x60Hz) */
+        {      18,1464,0,1051    }, /* 06 (1024x768x60Hz) */
+        {      1646,1406,1053,1038    }, /* 07 (1280x1024x60Hz) */
+        {      18,1464,0,1051    }  /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_StLCDDes1400x1050Data[]=
+{
+        {      9,1455,0,1051     },/* 00 (320x200,320x400,640x200,640x400) */
+        {      9,1455,0,1051     },/* 01 (320x350,640x350) */
+        {      9,1455,0,1051     },/* 02 (360x400,720x400) */
+        {      9,1455,0,1051     },/* 03 (720x350) */
+        {      9,1455,0,1051     },/* 04 (640x480x60Hz) */
+        {      9,1455,0,1051     },/* 05 (800x600x60Hz) */
+        {      9,1455,0,1051     },/* 06 (1024x768x60Hz) */
+        {      1637,1397,1053,1038     },/* 07 (1280x1024x60Hz) */
+        {      9,1455,0,1051     } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_ExtLCDDes1400x1050Data[]=
+{
+        {      9,1455,0,1051     },/* 00 (320x200,320x400,640x200,640x400) */
+        {      9,1455,0,1051     },/* 01 (320x350,640x350) */
+        {      9,1455,0,1051     },/* 02 (360x400,720x400) */
+        {      9,1455,0,1051     },/* 03 (720x350) */
+        {      9,1455,0,1051     },/* 04 (640x480x60Hz) */
+        {      9,1455,0,1051     },/* 05 (800x600x60Hz) */
+        {      9,1455,0,1051     },/* 06 (1024x768x60Hz) */
+        {      1637,1397,1053,1038     },/* 07 (1280x1024x60Hz) */
+        {      9,1455,0,1051     } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_CetLCDDes1400x1050Data[]=
+{
+        {      1308,1068,781,766    }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      1308,1068,781,766    }, /* 01 (320x350,640x350) */
+        {      1308,1068,781,766    }, /* 02 (360x400,720x400) */
+        {      1308,1068,781,766    }, /* 03 (720x350) */
+        {      1308,1068,781,766    }, /* 04 (640x480x60Hz) */
+        {      1388,1148,841,826    }, /* 05 (800x600x60Hz) */
+        {      1490,1250,925,910    }, /* 06 (1024x768x60Hz) */
+        {      1646,1406,1053,1038    }, /* 07 (1280x1024x60Hz) */
+        {      18,1464,0,1051    } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_CetLCDDes1400x1050Data2[]=
+{
+        {      0,1448,0,1051    }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      0,1448,0,1051    }, /* 01 (320x350,640x350) */
+        {      0,1448,0,1051    }, /* 02 (360x400,720x400) */
+        {      0,1448,0,1051    }, /* 03 (720x350) */
+        {      0,1448,0,1051    }  /* 04 (640x480x60Hz) */
+};
+
+
+
+XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1600x1200Data[]=
+{
+       {      18,1682,0,1201    }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      18,1682,0,1201    }, /* 01 (320x350,640x350) */
+        {      18,1682,0,1201    }, /* 02 (360x400,720x400) */
+        {      18,1682,0,1201    }, /* 03 (720x350) */
+        {      18,1682,0,1201    }, /* 04 (640x480x60Hz) */
+        {      18,1682,0,1201    }, /* 05 (800x600x60Hz) */
+        {      18,1682,0,1201    }, /* 06 (1024x768x60Hz) */
+        {      18,1682,0,1201    }, /* 07 (1280x1024x60Hz) */
+        {      18,1682,0,1201    }, /* 08 (1400x1050x60Hz) */
+        {      18,1682,0,1201    }  /* 09 (1600x1200x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_StLCDDLDes1600x1200Data[]=
+{
+        {      18,1682,1150,1101    }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      18,1682,1083,1034    }, /* 01 (320x350,640x350) */
+        {      18,1682,1150,1101    }, /* 02 (360x400,720x400) */
+        {      18,1682,1083,1034    }, /* 03 (720x350) */
+        {      18,1682,0,1201    }, /* 04 (640x480x60Hz) */
+        {      18,1682,0,1201    }, /* 05 (800x600x60Hz) */
+        {      18,1682,0,1201    }, /* 06 (1024x768x60Hz) */
+        {      18,1682,1232,1183    }, /* 07 (1280x1024x60Hz) */
+        {      18,1682,0,1201    }, /* 08 (1400x1050x60Hz) */
+        {      18,1682,0,1201    } /* 09 (1600x1200x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_ExtLCDDes1600x1200Data[]=
+{
+        {      9,1673,0,1201     },/* 00 (320x200,320x400,640x200,640x400) */
+        {      9,1673,0,1201     },/* 01 (320x350,640x350) */
+        {      9,1673,0,1201     },/* 02 (360x400,720x400) */
+        {      9,1673,0,1201     },/* 03 (720x350) */
+        {      9,1673,0,1201     },/* 04 (640x480x60Hz) */
+        {      9,1673,0,1201     },/* 05 (800x600x60Hz) */
+        {      9,1673,0,1201     },/* 06 (1024x768x60Hz) */
+        {      9,1673,0,1201     },/* 07 (1280x1024x60Hz) */
+        {      9,1673,0,1201     },/* 08 (1400x1050x60Hz) */
+        {      9,1673,0,1201     } /* 09 (1600x1200x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_StLCDDes1600x1200Data[]=
+{
+       {      9,1673,1150,1101     },/* 00 (320x200,320x400,640x200,640x400) */
+        {      9,1673,1083,1034     },/* 01 (320x350,640x350) */
+        {      9,1673,1150,1101     },/* 02 (360x400,720x400) */
+        {      9,1673,1083,1034     },/* 03 (720x350) */
+        {      9,1673,0,1201     },/* 04 (640x480x60Hz) */
+        {      9,1673,0,1201     },/* 05 (800x600x60Hz) */
+        {      9,1673,0,1201     },/* 06 (1024x768x60Hz) */
+        {      9,1673,1232,1183     },/* 07 (1280x1024x60Hz) */
+        {      9,1673,0,1201     },/* 08 (1400x1050x60Hz) */
+        {      9,1673,0,1201     } /* 09 (1600x1200x60Hz) */
+};
+
+XGI330_LCDDataDesStruct2  XGI_NoScalingDesData[]=
+{
+        {     9,657,448,405,96,2  }, /* 00 (320x200,320x400,640x200,640x400) */
+        {     9,657,448,355,96,2  }, /* 01 (320x350,640x350) */
+        {     9,657,448,405,96,2  }, /* 02 (360x400,720x400) */
+        {     9,657,448,355,96,2  }, /* 03 (720x350) */
+        {     9,657,1,483,96,2  }, /* 04 (640x480x60Hz) */
+        {     9,849,627,600,128,4  }, /* 05 (800x600x60Hz) */
+        {     9,1057,805,770,0136,6  }, /* 06 (1024x768x60Hz) */
+        {     9,1337,0,1025,112,3  }, /* 07 (1280x1024x60Hz) */
+        {     9,1457,0,1051,112,3  }, /* 08 (1400x1050x60Hz) }, //;[ycchen] 12/19/02 */
+        {     9,1673,0,1201,192,3  }, /* 09 (1600x1200x60Hz) */
+        {     9,1337,0,771,112,6  }  /* 0A (1280x768x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_ExtLCDDes1024x768x75Data[]=               /* ;;1024x768x75Hz */
+{
+        {9,1049,0,769},    /* ; 00 (320x200,320x400,640x200,640x400) */
+        {9,1049,0,769},    /* ; 01 (320x350,640x350) */
+        {9,1049,0,769},    /* ; 02 (360x400,720x400) */
+        {9,1049,0,769},    /* ; 03 (720x350) */
+        {9,1049,0,769},    /* ; 04 (640x480x75Hz) */
+        {9,1049,0,769},    /* ; 05 (800x600x75Hz) */
+        {9,1049,0,769}     /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_StLCDDes1024x768x75Data[]=
+{
+        {9,1049,0,769},    /* ; 00 (320x200,320x400,640x200,640x400) */
+        {9,1049,0,769},    /* ; 01 (320x350,640x350) */
+        {9,1049,0,769},    /* ; 02 (360x400,720x400) */
+        {9,1049,0,769},    /* ; 03 (720x350) */
+        {9,1049,0,769},    /* ; 04 (640x480x75Hz) */
+        {9,1049,0,769},    /* ; 05 (800x600x75Hz) */
+        {9,1049,0,769}     /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_CetLCDDes1024x768x75Data[]=       /* ;;1024x768x75Hz */
+{
+        {1152,856,622,587},     /* ; 00 (320x200,320x400,640x200,640x400) */
+        {1152,856,597,562},     /* ; 01 (320x350,640x350) */
+        {1192,896,622,587},     /* ; 02 (360x400,720x400) */
+        {1192,896,597,562},     /* ; 03 (720x350) */
+        {1129,857,656,625},     /* ; 04 (640x480x75Hz) */
+        {1209,937,716,685},     /* ; 05 (800x600x75Hz) */
+        {9,1049,0,769}                 /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1280x1024x75Data[]=         /* ;;1280x1024x75Hz */
+{
+        {18,1314,0,1025     },/* ; 00 (320x200,320x400,640x200,640x400) */
+        {18,1314,0,1025     },/* ; 01 (320x350,640x350) */
+        {18,1314,0,1025     },/* ; 02 (360x400,720x400) */
+        {18,1314,0,1025     },/* ; 03 (720x350) */
+        {18,1314,0,1025     },/* ; 04 (640x480x60Hz) */
+        {18,1314,0,1025     },/* ; 05 (800x600x60Hz) */
+        {18,1314,0,1025     },/* ; 06 (1024x768x60Hz) */
+        {18,1314,0,1025     }/* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_StLCDDLDes1280x1024x75Data[]=
+{
+        {18,1314,0,1025     },/* ; 00 (320x200,320x400,640x200,640x400) */
+        {18,1314,0,1025     },/* ; 01 (320x350,640x350) */
+        {18,1314,0,1025     },/* ; 02 (360x400,720x400) */
+        {18,1314,0,1025     },/* ; 03 (720x350) */
+        {18,1314,0,1025     },/* ; 04 (640x480x60Hz) */
+        {18,1314,0,1025     },/* ; 05 (800x600x60Hz) */
+        {18,1314,0,1025     },/* ; 06 (1024x768x60Hz) */
+        {18,1314,0,1025     }/* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_CetLCDDLDes1280x1024x75Data[]=    /* 1280x1024x75Hz */
+{
+        {1368,1008,752,711},    /* ; 00 (320x200,320x400,640x200,640x400) */
+        {1368,1008,729,688},    /* ; 01 (320x350,640x350) */
+        {1408,1048,752,711},    /* ; 02 (360x400,720x400) */
+        {1408,1048,729,688},    /* ; 03 (720x350) */
+        {1377,985,794,753},    /* ; 04 (640x480x75Hz) */
+        {1457,1065,854,813},    /* ; 05 (800x600x75Hz) */
+        {1569,1177,938,897},    /* ; 06 (1024x768x75Hz) */
+        {18,1314,0,1025}         /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_ExtLCDDes1280x1024x75Data[]=         /* ;;1280x1024x75Hz */
+{
+       {9,1305,0,1025},/* ; 00 (320x200,320x400,640x200,640x400) */
+        {9,1305,0,1025},/* ; 01 (320x350,640x350) */
+        {9,1305,0,1025},/* ; 02 (360x400,720x400) */
+        {9,1305,0,1025},/* ; 03 (720x350) */
+        {9,1305,0,1025},/* ; 04 (640x480x60Hz) */
+        {9,1305,0,1025},/* ; 05 (800x600x60Hz) */
+        {9,1305,0,1025},/* ; 06 (1024x768x60Hz) */
+        {9,1305,0,1025} /* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_StLCDDes1280x1024x75Data[]=
+{
+       {9,1305,0,1025},/* ; 00 (320x200,320x400,640x200,640x400) */
+        {9,1305,0,1025},/* ; 01 (320x350,640x350) */
+        {9,1305,0,1025},/* ; 02 (360x400,720x400) */
+        {9,1305,0,1025},/* ; 03 (720x350) */
+        {9,1305,0,1025},/* ; 04 (640x480x60Hz) */
+        {9,1305,0,1025},/* ; 05 (800x600x60Hz) */
+        {9,1305,0,1025},/* ; 06 (1024x768x60Hz) */
+        {9,1305,0,1025} /* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct  XGI_CetLCDDes1280x1024x75Data[]=      /* 1280x1024x75Hz */
+{
+        {1368,1008,752,711},    /* ; 00 (320x200,320x400,640x200,640x400) */
+        {1368,1008,729,688},    /* ; 01 (320x350,640x350) */
+        {1408,1048,752,711},    /* ; 02 (360x400,720x400) */
+        {1408,1048,729,688},    /* ; 03 (720x350) */
+        {1377,985,794,753},    /* ; 04 (640x480x75Hz) */
+        {1457,1065,854,813},    /* ; 05 (800x600x75Hz) */
+        {1569,1177,938,897},    /* ; 06 (1024x768x75Hz) */
+        {9,1305,0,1025}          /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[]= /* Scaling LCD 75Hz */
+{
+       {9,657,448,405,96,2},   /* ; 00 (320x200,320x400,640x200,640x400) */
+        {9,657,448,355,96,2},   /* ; 01 (320x350,640x350) */
+        {9,738,448,405,108,2},   /* ; 02 (360x400,720x400) */
+        {9,738,448,355,108,2},   /* ; 03 (720x350) */
+        {9,665,0,481,64,3},   /* ; 04 (640x480x75Hz) */
+        {9,825,0,601,80,3},   /* ; 05 (800x600x75Hz) */
+        {9,1049,0,769,96,3},   /* ; 06 (1024x768x75Hz) */
+        {9,1305,0,1025,144,3},   /* ; 07 (1280x1024x75Hz) */
+        {9,1457,0,1051,112,3},   /* ; 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */
+        {9,1673,0,1201,192,3},   /* ; 09 (1600x1200x75Hz) */
+        {9,1337,0,771,112,6}    /* ; 0A (1280x768x60Hz) */
+};
+
+XGI330_TVDataStruct  XGI_StPALData[]=
+{
+ {    1,   1, 864, 525,1270, 400, 100,   0, 760},
+ {    1,   1, 864, 525,1270, 350, 100,   0, 760},
+ {    1,   1, 864, 525,1270, 400,   0,   0, 720},
+ {    1,   1, 864, 525,1270, 350,   0,   0, 720},
+ {    1,   1, 864, 525,1270, 480,  50,   0, 760},
+ {    1,   1, 864, 525,1270, 600,  50,   0,   0}
+};
+
+XGI330_TVDataStruct  XGI_ExtPALData[]=
+{
+ {    2,   1,1080, 463,1270, 500,  50,   0,  50},
+ {   15,   7,1152, 413,1270, 500,  50,   0,  50},
+ {    2,   1,1080, 463,1270, 500,  50,   0,  50},
+ {   15,   7,1152, 413,1270, 500,  50,   0,  50},
+ {    2,   1, 900, 543,1270, 500,   0,   0,  50},
+ {    4,   3,1080, 663,1270, 500, 438,   0, 438},
+ {    1,   1,1125, 831,1270, 500, 686,   0, 686},     /*301b*/
+ {    3,   2,1080, 619,1270, 540, 438,   0, 438}
+};
+
+XGI330_TVDataStruct  XGI_StNTSCData[]=
+{
+ {    1,   1, 858, 525,1270, 400,  50,   0, 760},
+ {    1,   1, 858, 525,1270, 350,  50,   0, 640},
+ {    1,   1, 858, 525,1270, 400,   0,   0, 720},
+ {    1,   1, 858, 525,1270, 350,   0,   0, 720},
+ {    1,   1, 858, 525,1270, 480,   0,   0, 760}
+};
+
+XGI330_TVDataStruct  XGI_ExtNTSCData[]=
+{
+ {    9,  5, 1001, 453,1270, 420, 171,   0, 171},
+ {   12,  5,  858, 403,1270, 420, 171,   0, 171},
+ {    9,  5, 1001, 453,1270, 420, 171,   0, 171},
+ {   12,  5,  858, 403,1270, 420, 171,   0, 171},
+ {  143,  80, 836, 523,1270, 420, 224,   0,   0},
+ {  143, 120,1008, 643,1270, 420,   0,   1,   0},
+ {   1,    1,1120, 821,1516, 420,   0,   1,   0}, /*301b*/
+ {    2,   1, 858, 503,1584, 480,   0,   1,   0},
+ {    3,   2,1001, 533,1270, 420,   0,   0,   0}
+};
+
+XGI330_TVDataStruct  XGI_St1HiTVData[]=
+{
+       {        1,1,892,563,690,800,0,0,0               }, /* 00 (320x200,320x400,640x200,640x400) */
+        {        1,1,892,563,690,700,0,0,0               }, /* 01 (320x350,640x350) */
+        {        1,1,1000,563,785,800,0,0,0              }, /* 02 (360x400,720x400) */
+        {        1,1,1000,563,785,700,0,0,0              }, /* 03 (720x350) */
+        {        1,1,892,563,690,960,0,0,0               }, /* 04 (320x240,640x480) */
+        {        8,5,1050,683,1648,960,0x150,1,0         }  /* 05 (400x300,800x600) */
+};
+
+XGI330_TVDataStruct  XGI_St2HiTVData[]=
+{
+        {        3,1,840,483,1648,960,0x032,0,0          }, /* 00 (320x200,320x400,640x200,640x400) */
+        {        1,1,892,563,690,700,0,0,0               }, /* 01 (320x350,640x350) */
+        {        3,1,840,483,1648,960,0x032,0,0          }, /* 02 (360x400,720x400) */
+        {        1,1,1000,563,785,700,0,0,0              }, /* 03 (720x350) */
+        {        5,2,840,563,1648,960,0x08D,1,0          }, /* 04 (320x240,640x480) */
+        {        8,5,1050,683,1648,960,0x17C,1,0         }  /* 05 (400x300,800x600) */
+
+};
+
+XGI330_TVDataStruct  XGI_ExtHiTVData[]=
+{
+        {        6,1,840,563,1632,960,0,0,0              }, /* 00 (320x200,320x400,640x200,640x400) */
+        {        3,1,960,563,1632,960,0,0,0              }, /* 01 (320x350,640x350) */
+        {        3,1,840,483,1632,960,0,0,0              }, /* 02 (360x400,720x400) */
+        {        3,1,960,563,1632,960,0,0,0              }, /* 03 (720x350) */
+        {        5,1,840,563,1648,960,0x166,1,0          }, /* 04 (320x240,640x480) */
+        {        16,5,1050,683,1648,960,0x143,1,0        }, /* 05 (400x300,800x600) */
+        {        25,12,1260,851,1648,960,0x032,0,0       }, /* 06 (512x384,1024x768) */
+        {        5,4,1575,1124,1648,960,0x128,0,0        }, /* 07 (1280x1024) */
+        {        4,1,1050,563,1548,960,0x143,1,0         }, /* 08 (800x480) */
+        {        5,2,1400,659,1648,960,0x032,0,0         }, /* 09 (1024x576) */
+        {        8,5,1750,803,1648,960,0x128,0,0         }  /* 0A (1280x720) */
+
+};
+
+XGI330_TVDataStruct  XGI_ExtYPbPr525iData[]=
+{
+ {    9,  5, 1001, 453,1270, 420, 171,   0, 171},
+ {   12,  5,  858, 403,1270, 420, 171,   0, 171},
+ {    9,  5, 1001, 453,1270, 420, 171,   0, 171},
+ {   12,  5,  858, 403,1270, 420, 171,   0, 171},
+ {  143,  80, 836, 523,1250, 420, 224,   0,   0},
+ {  143, 120,1008, 643,1250, 420,   0,   1,   0},
+ {   1,    1,1120, 821,1516, 420,   0,   1,   0}, /*301b*/
+ {    2,   1, 858, 503,1584, 480,   0,   1,   0},
+ {    3,   2,1001, 533,1250, 420,   0,   0,   0}
+};
+
+XGI330_TVDataStruct  XGI_StYPbPr525iData[]=
+{
+ {    1,   1, 858, 525,1270, 400,  50,   0, 760},
+ {    1,   1, 858, 525,1270, 350,  50,   0, 640},
+ {    1,   1, 858, 525,1270, 400,   0,   0, 720},
+ {    1,   1, 858, 525,1270, 350,   0,   0, 720},
+ {    1,   1, 858, 525,1270, 480,   0,   0, 760},
+};
+
+XGI330_TVDataStruct  XGI_ExtYPbPr525pData[]=
+{
+ {    9,  5, 1001, 453,1270, 420, 171,   0, 171},
+ {   12,  5,  858, 403,1270, 420, 171,   0, 171},
+ {    9,  5, 1001, 453,1270, 420, 171,   0, 171},
+ {   12,  5,  858, 403,1270, 420, 171,   0, 171},
+ {  143,  80, 836, 523,1270, 420, 224,   0,   0},
+ {  143, 120,1008, 643,1270, 420,   0,   1,   0},
+ {   1,    1,1120, 821,1516, 420,   0,   1,   0}, /*301b*/
+ {    2,   1, 858, 503,1584, 480,   0,   1,   0},
+ {    3,   2,1001, 533,1270, 420,   0,   0,   0}
+ };
+
+XGI330_TVDataStruct  XGI_StYPbPr525pData[]=
+{
+ {    1,   1,1716, 525,1270, 400,  50,   0, 760},
+ {    1,   1,1716, 525,1270, 350,  50,   0, 640},
+ {    1,   1,1716, 525,1270, 400,   0,   0, 720},
+ {    1,   1,1716, 525,1270, 350,   0,   0, 720},
+ {    1,   1,1716, 525,1270, 480,   0,   0, 760},
+};
+
+XGI330_TVDataStruct  XGI_ExtYPbPr750pData[]=
+{
+ {    3,   1, 935, 470,1130, 680,  50,   0,   0},       /* 00 (320x200,320x400,640x200,640x400) */
+ {   24,   7, 935, 420,1130, 680,  50,   0,   0},       /* 01 (320x350,640x350) */
+ {    3,   1, 935, 470,1130, 680,  50,   0,   0},       /* 02 (360x400,720x400) */
+ {   24,   7, 935, 420,1130, 680,  50,   0,   0},       /* 03 (720x350) */
+ {    2,   1,1100, 590,1130, 640,  50,   0,   0},       /* 04 (320x240,640x480) */
+ {    3,   2,1210, 690,1130, 660,  50,   0,   0},       /* 05 (400x300,800x600) */
+ {    1,   1,1375, 878,1130, 640, 638,   0,   0},       /* 06 (1024x768) */
+ {    2,   1, 858, 503,1130, 480,   0,   1,   0},        /* 07 (720x480) */
+ {    5,   4,1815, 570,1130, 660,  50,   0,   0},
+ {    5,   3,1100, 686,1130, 640,  50,   1,   0},
+ {   10,   9,1320, 830,1130, 640,  50,   0,   0}
+};
+
+XGI330_TVDataStruct  XGI_StYPbPr750pData[]=
+{
+ {    1,   1,1650, 750,1280, 400,  50,   0, 760},
+ {    1,   1,1650, 750,1280, 350,  50,   0, 640},
+ {    1,   1,1650, 750,1280, 400,   0,   0, 720},
+ {    1,   1,1650, 750,1280, 350,   0,   0, 720},
+ {    1,   1,1650, 750,1280, 480,   0,   0, 760},
+};
+
+UCHAR XGI330_NTSCTiming[] = {
+  0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
+  0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
+  0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
+  0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
+  0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
+  0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40,
+  0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50,
+  0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00};
+
+UCHAR XGI330_PALTiming[] = {
+  0x21,0x5A,0x35,0x6e,0x04,0x38,0x3d,0x70,
+  0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
+  0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
+  0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17,
+  0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02,
+  0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40,
+  0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63,
+  0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00};
+
+UCHAR XGI330_HiTVExtTiming[] =
+{
+      0x2D,0x60,0x2C,0x5F,0x08,0x31,0x3A,0x64,
+      0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+      0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
+      0x64,0x90,0x33,0x8C,0x18,0x36,0x3E,0x13,
+      0x2A,0xDE,0x2A,0x44,0x40,0x2A,0x44,0x40,
+      0x8E,0x8E,0x82,0x07,0x0B,
+      0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+      0x60,0x14,0x3D,0x63,0x4F,
+      0x27,0x00,0xfc,0xff,0x6a,0x00
+
+};
+
+UCHAR XGI330_HiTVSt1Timing[] =
+{
+      0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x65,
+      0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+      0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
+      0x65,0x90,0x7B,0xA8,0x03,0xF0,0x87,0x03,
+      0x11,0x15,0x11,0xCF,0x10,0x11,0xCF,0x10,
+      0x35,0x35,0x3B,0x69,0x1D,
+      0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+      0x60,0x04,0x86,0xAF,0x5D,
+      0x0E,0x00,0xfc,0xff,0x2d,0x00
+};
+
+UCHAR XGI330_HiTVSt2Timing[] =
+{
+      0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x64,
+      0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+      0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
+      0x64,0x90,0x33,0x8C,0x18,0x36,0x3E,0x13,
+      0x2A,0xDE,0x2A,0x44,0x40,0x2A,0x44,0x40,
+      0x8E,0x8E,0x82,0x07,0x0B,
+      0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+      0x60,0x14,0x3D,0x63,0x4F,
+      0x27,0x00,0xFC,0xff,0x6a,0x00
+};
+
+UCHAR XGI330_HiTVTextTiming[] =
+{
+      0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x65,
+      0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+      0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
+      0x65,0x90,0xE7,0xBC,0x03,0x0C,0x97,0x03,
+      0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20,
+      0xC8,0xC8,0x3B,0xD2,0x26,
+      0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+      0x60,0x04,0x96,0x72,0x5C,
+      0x11,0x00,0xFC,0xFF,0x32,0x00
+};
+
+UCHAR XGI330_YPbPr750pTiming[] =
+{
+      0x30,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
+      0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
+      0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+      0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13,
+      0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
+      0x4b,0x4b,0x6f,0x2f,0x63,
+      0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+      0x60,0x14,0x73,0x00,0x40,
+      0x11,0x00,0xfc,0xff,0x32,0x00
+};
+
+UCHAR XGI330_YPbPr525pTiming[] =
+{
+      0x3E,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
+      0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
+      0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+      0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
+      0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
+      0x51,0x5e,0x60,0x49,0x7d,
+      0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+      0x60,0x14,0x4B,0x43,0x41,
+      0x11,0x00,0xFC,0xFF,0x32,0x00
+};
+
+UCHAR XGI330_YPbPr525iTiming[] =
+{
+      0x1B,0x21,0x03,0x09,0x05,0x06,0x0C,0x0C,
+      0x94,0x49,0x01,0x0A,0x06,0x0D,0x04,0x0A,
+      0x06,0x14,0x0D,0x04,0x0A,0x00,0x85,0x1B,
+      0x0C,0x50,0x00,0x97,0x00,0xDA,0x4A,0x17,
+      0x7D,0x05,0x4B,0x00,0x00,0xE2,0x00,0x02,
+      0x03,0x0A,0x65,0x9D,0x08,
+      0x92,0x8F,0x40,0x60,0x80,0x14,0x90,0x8C,
+      0x60,0x14,0x4B,0x00,0x40,
+      0x44,0x00,0xDB,0x02,0x3B,0x00
+
+};
+
+UCHAR XGI330_HiTVGroup3Data[] =
+{
+      0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0x5F,
+      0x05,0x21,0xB2,0xB2,0x55,0x77,0x2A,0xA6,
+      0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20,
+      0x8C,0x6E,0x60,0x2E,0x58,0x48,0x72,0x44,
+      0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80,
+      0x4F,0x7F,0x03,0xA8,0x7D,0x20,0x1A,0xA9,
+      0x14,0x05,0x03,0x7E,0x64,0x31,0x14,0x75,
+      0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
+};
+
+UCHAR XGI330_HiTVGroup3Simu[] =
+{
+      0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0x95,
+      0xDB,0x20,0xB8,0xB8,0x55,0x47,0x2A,0xA6,
+      0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20,
+      0x8C,0x6E,0x60,0x15,0x26,0xD3,0xE4,0x11,
+      0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80,
+      0x67,0x36,0x01,0x47,0x0E,0x10,0xBE,0xB4,
+      0x01,0x05,0x03,0x7E,0x65,0x31,0x14,0x75,
+      0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
+};
+
+UCHAR XGI330_HiTVGroup3Text[] =
+{
+      0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0xA7,
+      0xF5,0x20,0xCE,0xCE,0x55,0x47,0x2A,0xA6,
+      0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20,
+      0x8C,0x6E,0x60,0x18,0x2C,0x0C,0x20,0x22,
+      0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80,
+      0x93,0x3C,0x01,0x50,0x2F,0x10,0xF4,0xCA,
+      0x01,0x05,0x03,0x7E,0x65,0x31,0x14,0x75,
+      0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
+};
+
+UCHAR XGI330_Ren525pGroup3[] =
+{
+  0x00,0x14,0x15,0x25,0x55,0x15,0x0b,0x13,
+  0xB1,0x41,0x62,0x62,0xFF,0xF4,0x45,0xa6,
+  0x25,0x2F,0x67,0xF6,0xbf,0xFF,0x8E,0x20,
+  0xAC,0xDA,0x60,0xFe,0x6A,0x9A,0x06,0x10,
+  0xd1,0x04,0x18,0x0a,0xFF,0x80,0x00,0x80,
+  0x3c,0x77,0x00,0xEF,0xE0,0x10,0xB0,0xE0,
+  0x10,0x4F,0x0F,0x0F,0x05,0x0F,0x08,0x6E,
+  0x1a,0x1F,0x25,0x2a,0x4C,0xAA,0x01
+};
+
+UCHAR XGI330_Ren750pGroup3[] =
+{
+  0x00,0x14,0x15,0x25,0x55,0x15,0x0b,0x7a,
+  0x54,0x41,0xE7,0xE7,0xFF,0xF4,0x45,0xa6,
+  0x25,0x2F,0x67,0xF6,0xbf,0xFF,0x8E,0x20,
+  0xAC,0x6A,0x60,0x2b,0x52,0xCD,0x61,0x10,
+  0x51,0x04,0x18,0x0a,0x1F,0x80,0x00,0x80,
+  0xFF,0xA4,0x04,0x2B,0x94,0x21,0x72,0x94,
+  0x26,0x05,0x01,0x0F,0xed,0x0F,0x0A,0x64,
+  0x18,0x1D,0x23,0x28,0x4C,0xAA,0x01
+};
+
+XGI_PanelDelayTblStruct XGI330_PanelDelayTbl[]=
+{
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}}
+};
+
+XGI330_LVDSDataStruct  XGI330_LVDS320x480Data_1[]=
+{
+ {848, 433,400,525},
+ {848, 389,400,525},
+ {848, 433,400,525},
+ {848, 389,400,525},
+ {848, 518,400, 525},
+ {1056, 628,400,525},
+ {400, 525,400,525},
+ {800, 449,1000, 644},
+ {800, 525,1000, 635}
+};
+
+XGI330_LVDSDataStruct  XGI330_LVDS800x600Data_1[]=
+{
+ {848, 433,1060, 629},
+ {848, 389,1060, 629},
+ {848, 433,1060, 629},
+ {848, 389,1060, 629},
+ {848, 518,1060, 629},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {800, 449,1000, 644},
+ {800, 525,1000, 635}
+};
+
+XGI330_LVDSDataStruct  XGI330_LVDS800x600Data_2[]=
+{
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {800, 449,1000, 644},
+ {800, 525,1000, 635}
+};
+
+XGI330_LVDSDataStruct  XGI_LVDS1024x768Data_1[]=
+{
+ { 960 , 438 , 1344 , 806 } ,  /* 00 (320x200,320x400,640x200,640x400) */
+ { 960 , 388 , 1344 , 806 } ,  /* 01 (320x350,640x350) */
+ { 1040, 438 , 1344 , 806 } ,  /* 02 (360x400,720x400) */
+ { 1040, 388 , 1344 , 806 } ,  /* 03 (720x350) */
+ { 960 , 518 , 1344 , 806 } ,  /* 04 (320x240,640x480) */
+ {1120 , 638 , 1344 , 806 } ,  /* 05 (400x300,800x600) */
+ {1344 , 806 , 1344 , 806 }    /* 06 (512x384,1024x768) */
+};
+
+
+XGI330_LVDSDataStruct  XGI_LVDS1024x768Data_2[]=
+{
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {800, 449,1280, 801},
+ {800, 525,1280, 813}
+};
+
+XGI330_LVDSDataStruct  XGI_LVDS1280x1024Data_1[]=
+{
+ {1048, 442,1688, 1066},
+ {1048, 392,1688, 1066},
+ {1048, 442,1688, 1066},
+ {1048, 392,1688, 1066},
+ {1048, 522,1688, 1066},
+ {1208, 642,1688, 1066},
+ {1432, 810,1688, 1066},
+ {1688, 1066,1688, 1066}
+};
+
+XGI330_LVDSDataStruct  XGI_LVDS1280x1024Data_2[]=
+{
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {800, 449,1280, 801},
+ {800, 525,1280, 813}
+};
+/*
+XGI330_LVDSDataStruct  XGI_LVDS1280x768Data_1[]=
+{
+ {768,438,1408,806},
+ {768,388,1408,806},
+ {768,438,1408,806},
+ {768,388,1408,806},
+ {768,518,1408,806},
+ {928,638,1408,806},
+ {1408,806,1408,806},
+ {1408,806,1408,806},
+ {1408,806,1408,806}
+};
+
+XGI330_LVDSDataStruct  XGI_LVDS1280x768Data_2[]=
+{
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806}
+};
+
+XGI330_LVDSDataStruct  XGI_LVDS1280x768NData_1[]=
+{
+ {704, 438,1344, 806},
+ {704, 388,1344, 806},
+ {704, 438,1344, 806},
+ {704, 388,1344, 806},
+ {704, 518,1344, 806},
+ {864, 638,1344, 806},
+ {1088, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806}
+};
+
+XGI330_LVDSDataStruct  XGI_LVDS1280x768NData_2[]=
+{
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806}
+};
+
+XGI330_LVDSDataStruct  XGI_LVDS1280x768SData_1[]=
+{
+ {1048,438,1688,806},
+ {1048,388,1688,806},
+ {1148,438,1688,806},
+ {1148,388,1688,806},
+ {1048,518,1688,806},
+ {1208,638,1688,806},
+ {1432,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806}
+};
+
+XGI330_LVDSDataStruct  XGI_LVDS1280x768SData_2[]=
+{
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806}
+};
+*/
+XGI330_LVDSDataStruct  XGI_LVDS1400x1050Data_1[]=
+{
+ {928,416,1688,1066},
+ {928,366,1688,1066},
+ {928,416,1688,1066},
+ {928,366,1688,1066},
+ {928,496,1688,1066},
+ {1088,616,1688,1066},
+ {1312,784,1688,1066},
+ {1568,1040,1688,1066},
+ {1688,1066,1688,1066}
+};
+
+XGI330_LVDSDataStruct  XGI_LVDS1400x1050Data_2[]=
+{
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066}
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1600x1200Data_1[]=
+{      /* ;;[ycchen] 12/05/02 LCDHTxLCDVT=2048x1320 */
+        {        1088,520,2048,1320      },/* 00 (320x200,320x400,640x200,640x400) */
+        {        1088,470,2048,1320      },/* 01 (320x350,640x350) */
+        {        1088,520,2048,1320      },/* 02 (360x400,720x400) */
+        {        1088,470,2048,1320      },/* 03 (720x350) */
+        {        1088,600,2048,1320      },/* 04 (320x240,640x480) */
+        {        1248,720,2048,1320      },/* 05 (400x300,800x600) */
+        {        1472,888,2048,1320      },/* 06 (512x384,1024x768) */
+        {        1728,1144,2048,1320     },/* 07 (640x512,1280x1024) */
+        {        1848,1170,2048,1320     },/* 08 (1400x1050) */
+        {        2048,1320,2048,1320     } /* 09 (1600x1200) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDSNoScalingData[]=
+{
+        {        800,449,800,449             }, /* 00 (320x200,320x400,640x200,640x400) */
+        {        800,449,800,449             }, /* 01 (320x350,640x350) */
+        {        800,449,800,449             }, /* 02 (360x400,720x400) */
+        {        800,449,800,449             }, /* 03 (720x350) */
+        {        800,525,800,525             }, /* 04 (640x480x60Hz) */
+        {        1056,628,1056,628           }, /* 05 (800x600x60Hz) */
+        {        1344,806,1344,806           }, /* 06 (1024x768x60Hz) */
+        {        1688,1066,1688,1066         }, /* 07 (1280x1024x60Hz) */
+        {        1688,1066,1688,1066         }, /* 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */
+        {        2160,1250,2160,1250         }, /* 09 (1600x1200x60Hz) */
+        {        1688,806,1688,806           }  /* 0A (1280x768x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1x75[]=
+{
+       {960,438,1312,800  }, /* 00 (320x200,320x400,640x200,640x400) */
+        {960,388,1312,800  }, /* 01 (320x350,640x350) */
+        {1040,438,1312,800 }, /* 02 (360x400,720x400) */
+        {1040,388,1312,800 }, /* 03 (720x350) */
+        {928,512,1312,800  }, /* 04 (320x240,640x480) */
+        {1088,632,1312,800 }, /* 05 (400x300,800x600) */
+        {1312,800,1312,800 }, /* 06 (512x384,1024x768) */
+};
+
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2x75[]=
+{
+        {1312,800,1312,800}, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {1312,800,1312,800}, /* ; 01 (320x350,640x350) */
+        {1312,800,1312,800}, /* ; 02 (360x400,720x400) */
+        {1312,800,1312,800}, /* ; 03 (720x350) */
+        {1312,800,1312,800}, /* ; 04 (320x240,640x480) */
+        {1312,800,1312,800}, /* ; 05 (400x300,800x600) */
+        {1312,800,1312,800}, /* ; 06 (512x384,1024x768) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1x75[]=
+{
+        {1048,442,1688,1066  }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {1048,392,1688,1066  }, /* ; 01 (320x350,640x350) */
+        {1128,442,1688,1066  }, /* ; 02 (360x400,720x400) */
+        {1128,392,1688,1066  }, /* ; 03 (720x350) */
+        {1048,522,1688,1066  }, /* ; 04 (320x240,640x480) */
+        {1208,642,1688,1066  }, /* ; 05 (400x300,800x600) */
+        {1432,810,1688,1066  }, /* ; 06 (512x384,1024x768) */
+        {1688,1066,1688,1066 }, /* ; 06; 07 (640x512,1280x1024) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2x75[]=
+{
+        {1688,1066,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {1688,1066,1688,1066 }, /* ; 01 (320x350,640x350) */
+        {1688,1066,1688,1066 }, /* ; 02 (360x400,720x400) */
+        {1688,1066,1688,1066 }, /* ; 03 (720x350) */
+        {1688,1066,1688,1066 }, /* ; 04 (320x240,640x480) */
+        {1688,1066,1688,1066 }, /* ; 05 (400x300,800x600) */
+        {1688,1066,1688,1066 }, /* ; 06 (512x384,1024x768) */
+        {1688,1066,1688,1066 }, /* ; 06; 07 (640x512,1280x1024) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDSNoScalingDatax75[]=
+{
+        {800,449,800,449     }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {800,449,800,449     }, /* ; 01 (320x350,640x350) */
+        {900,449,900,449     }, /* ; 02 (360x400,720x400) */
+        {900,449,900,449     }, /* ; 03 (720x350) */
+        {800,500,800,500     }, /* ; 04 (640x480x75Hz) */
+        {1056,625,1056,625   }, /* ; 05 (800x600x75Hz) */
+        {1312,800,1312,800   }, /* ; 06 (1024x768x75Hz) */
+        {1688,1066,1688,1066 }, /* ; 07 (1280x1024x75Hz) */
+        {1688,1066,1688,1066 }, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */
+        {2160,1250,2160,1250 }, /* ; 09 (1600x1200x75Hz) */
+        {1688,806,1688,806   }, /* ; 0A (1280x768x75Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1[]=
+{
+       {      0,1048,   0, 771     }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      0,1048,   0, 771     }, /* 01 (320x350,640x350) */
+        {      0,1048,   0, 771     }, /* 02 (360x400,720x400) */
+        {      0,1048,   0, 771     }, /* 03 (720x350) */
+        {      0,1048,   0, 771     }, /* 04 (640x480x60Hz) */
+        {      0,1048,   0, 771     }, /* 05 (800x600x60Hz) */
+        {      0,1048, 805, 770     }  /* 06 (1024x768x60Hz) */
+} ;
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2[]=
+{
+       {      1142, 856, 622, 587     }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      1142, 856, 597, 562     }, /* 01 (320x350,640x350) */
+        {      1142, 856, 622, 587     }, /* 02 (360x400,720x400) */
+        {      1142, 856, 597, 562     }, /* 03 (720x350) */
+        {      1142,1048, 722, 687     }, /* 04 (640x480x60Hz) */
+        {      1232, 936, 722, 687     }, /* 05 (800x600x60Hz) */
+        {         0,1048, 805, 771     }  /* 06 (1024x768x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3[]=
+{
+       {       320,  24, 622, 587     }, /* 00 (320x200,320x400,640x200,640x400) */
+        {       320,  24, 597, 562     }, /* 01 (320x350,640x350) */
+        {       320,  24, 622, 587     }, /* 02 (360x400,720x400) */
+        {       320,  24, 597, 562     }, /* 03 (720x350) */
+        {       320,  24, 722, 687     }  /* 04 (640x480x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1[]=
+{
+       {      0,1328,    0, 1025     }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      0,1328,    0, 1025     }, /* 01 (320x350,640x350) */
+        {      0,1328,    0, 1025     }, /* 02 (360x400,720x400) */
+        {      0,1328,    0, 1025     }, /* 03 (720x350) */
+        {      0,1328,    0, 1025     }, /* 04 (640x480x60Hz) */
+        {      0,1328,    0, 1025     }, /* 05 (800x600x60Hz) */
+        {      0,1328,    0, 1025     }, /* 06 (1024x768x60Hz) */
+        {      0,1328, 1065, 1024     }  /* 07 (1280x1024x60Hz) */
+};
+
+ /* The Display setting for DE Mode Panel */
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2[]=
+{
+       {      1368,1008,752,711     }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      1368,1008,729,688     }, /* 01 (320x350,640x350) */
+        {      1408,1048,752,711     }, /* 02 (360x400,720x400) */
+        {      1408,1048,729,688     }, /* 03 (720x350) */
+        {      1368,1008,794,753     }, /* 04 (640x480x60Hz) */
+        {      1448,1068,854,813     }, /* 05 (800x600x60Hz) */
+        {      1560,1200,938,897     }, /* 06 (1024x768x60Hz) */
+        {      0000,1328,0,1025     }  /* 07 (1280x1024x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_1[]=
+{
+       {      0,1448,0,1051     }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      0,1448,0,1051     }, /* 01 (320x350,640x350) */
+        {      0,1448,0,1051     }, /* 02 (360x400,720x400) */
+        {      0,1448,0,1051     }, /* 03 (720x350) */
+        {      0,1448,0,1051     }, /* 04 (640x480x60Hz) */
+        {      0,1448,0,1051     }, /* 05 (800x600x60Hz) */
+        {      0,1448,0,1051     }, /* 06 (1024x768x60Hz) */
+        {      0,1448,0,1051     }, /* 07 (1280x1024x60Hz) */
+        {      0,1448,0,1051     }  /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_2[]=
+{
+       {      1308,1068, 781, 766     }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      1308,1068, 781, 766     }, /* 01 (320x350,640x350) */
+        {      1308,1068, 781, 766     }, /* 02 (360x400,720x400) */
+        {      1308,1068, 781, 766     }, /* 03 (720x350) */
+        {      1308,1068, 781, 766     }, /* 04 (640x480x60Hz) */
+        {      1388,1148, 841, 826     }, /* 05 (800x600x60Hz) */
+        {      1490,1250, 925, 910     }, /* 06 (1024x768x60Hz) */
+        {      1608,1368,1053,1038     }, /* 07 (1280x1024x60Hz) */
+        {      0,1448,0,1051     }  /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1600x1200Des_1[]=
+{
+       {      0,1664,0,1201     }, /* 00 (320x200,320x400,640x200,640x400) */
+        {      0,1664,0,1201     }, /* 01 (320x350,640x350) */
+        {      0,1664,0,1201     }, /* 02 (360x400,720x400) */
+        {      0,1664,0,1201     }, /* 03 (720x350) */
+        {      0,1664,0,1201     }, /* 04 (640x480x60Hz) */
+        {      0,1664,0,1201     }, /* 05 (800x600x60Hz) */
+        {      0,1664,0,1201     }, /* 06 (1024x768x60Hz) */
+        {      0,1664,0,1201     }, /* 07 (1280x1024x60Hz) */
+        {      0,1664,0,1201     }, /* 08 (1400x1050x60Hz) */
+        {      0,1664,0,1201     }  /* 09 (1600x1200x60Hz) */
+};
+
+
+
+XGI330_LCDDataDesStruct2  XGI_LVDSNoScalingDesData[]=
+{
+       {     0, 648, 448, 405,  96,   2   }, /* 00 (320x200,320x400,640x200,640x400) */
+        {     0, 648, 448, 355,  96,   2   }, /* 01 (320x350,640x350) */
+        {     0, 648, 448, 405,  96,   2   }, /* 02 (360x400,720x400) */
+        {     0, 648, 448, 355,  96,   2   }, /* 03 (720x350) */
+        {     0, 648,  1, 483,  96,   2   }, /* 04 (640x480x60Hz) */
+        {     0, 840, 627, 600, 128,   4   }, /* 05 (800x600x60Hz) */
+        {     0,1048, 805, 770, 136,   6   }, /* 06 (1024x768x60Hz) */
+        {     0,1328,0,1025, 112,   3   }, /* 07 (1280x1024x60Hz) */
+        {     0,1438,0,1051, 112,   3   }, /* 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */
+        {     0,1664,0,1201, 192,   3   }, /* 09 (1600x1200x60Hz) */
+        {     0,1328,0,0771, 112,   6   }  /* 0A (1280x768x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1x75[]=                      /* ; 1024x768 Full-screen */
+{
+        {0,1040,0,769}, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {0,1040,0,769}, /* ; 01 (320x350,640x350) */
+        {0,1040,0,769}, /* ; 02 (360x400,720x400) */
+        {0,1040,0,769}, /* ; 03 (720x350) */
+        {0,1040,0,769}, /* ; 04 (640x480x75Hz) */
+        {0,1040,0,769}, /* ; 05 (800x600x75Hz) */
+        {0,1040,0,769} /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2x75[]= /* ; 1024x768 center-screen (Enh. Mode) */
+{
+        {1142, 856,622,587 }, /* 00 (320x200,320x400,640x200,640x400) */
+        {1142, 856,597,562 }, /* 01 (320x350,640x350) */
+        {1142, 856,622,587 }, /* 02 (360x400,720x400) */
+        {1142, 856,597,562 }, /* 03 (720x350) */
+        {1142,1048,722,687 }, /* 04 (640x480x60Hz) */
+        {1232, 936,722,687 }, /* 05 (800x600x60Hz) */
+        {   0,1048,805,771 }  /* 06 (1024x768x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3x75[]= /* ; 1024x768 center-screen (St.Mode) */
+{
+        {320,24,622,587  }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {320,24,597,562  }, /* ; 01 (320x350,640x350) */
+        {320,24,622,587  }, /* ; 02 (360x400,720x400) */
+        {320,24,597,562  }, /* ; 03 (720x350) */
+        {320,24,722,687  } /* ; 04 (640x480x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1x75[]=
+{
+        {0,1296,0,1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {0,1296,0,1025}, /* ; 01 (320x350,640x350) */
+        {0,1296,0,1025}, /* ; 02 (360x400,720x400) */
+        {0,1296,0,1025}, /* ; 03 (720x350) */
+        {0,1296,0,1025}, /* ; 04 (640x480x75Hz) */
+        {0,1296,0,1025}, /* ; 05 (800x600x75Hz) */
+        {0,1296,0,1025}, /* ; 06 (1024x768x75Hz) */
+        {0,1296,0,1025} /* ; 07 (1280x1024x75Hz) */
+};
+
+/* The Display setting for DE Mode Panel */
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2x75[]=   /* [ycchen] 02/18/03 Set DE as default */
+{
+        {1368,976,752,711 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        {1368,976,729,688 }, /* ; 01 (320x350,640x350) */
+        {1408,976,752,711 }, /* ; 02 (360x400,720x400) */
+        {1408,976,729,688 }, /* ; 03 (720x350) */
+        {1368,976,794,753 }, /* ; 04 (640x480x75Hz) */
+        {1448,1036,854,813}, /* ; 05 (800x600x75Hz) */
+        {1560,1168,938,897}, /* ; 06 (1024x768x75Hz) */
+        {0,1296,0,1025    } /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[]=  /* Scaling LCD 75Hz */
+{
+       { 0,648,448,405,96,2  }, /* ; 00 (320x200,320x400,640x200,640x400) */
+       { 0,648,448,355,96,2  }, /* ; 01 (320x350,640x350) */
+       { 0,729,448,405,108,2 }, /* ; 02 (360x400,720x400) */
+       { 0,729,448,355,108,2 }, /* ; 03 (720x350) */
+       { 0,656,0,481,64,3    }, /* ; 04 (640x480x75Hz) */
+       { 0,816,0,601,80,3    }, /* ; 05 (800x600x75Hz) */
+       { 0,1040,0,769,96,3   }, /* ; 06 (1024x768x75Hz) */
+       { 0,1296,0,1025,144,3 }, /* ; 07 (1280x1024x75Hz) */
+       { 0,1448,0,1051,112,3 }, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */
+       { 0,1664,0,1201,192,3 }, /* ; 09 (1600x1200x75Hz) */
+       { 0,1328,0,771,112,6  }  /* ; 0A (1280x768x75Hz) */
+};
+
+XGI330_LVDSDataStruct  XGI330_LVDS640x480Data_1[]=
+{
+ {800, 449, 800, 449},
+ {800, 449, 800, 449},
+ {800, 449, 800, 449},
+ {800, 449, 800, 449},
+ {800, 525, 800, 525},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628}
+};
+
+XGI330_CHTVDataStruct  XGI_CHTVUNTSCData[]=
+{
+ {840, 600, 840, 600},
+ {840, 600, 840, 600},
+ {840, 600, 840, 600},
+ {840, 600, 840, 600},
+ {784, 600, 784, 600},
+ {1064, 750,1064, 750}
+};
+
+XGI330_CHTVDataStruct  XGI_CHTVONTSCData[]=
+{
+ {840, 525, 840, 525},
+ {840, 525, 840, 525},
+ {840, 525, 840, 525},
+ {840, 525, 840, 525},
+ {784, 525, 784, 525},
+ {1040, 700,1040, 700}
+};
+
+XGI330_CHTVDataStruct  XGI_CHTVUPALData[]=
+{
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {840, 750, 840, 750},
+ {936, 836, 936, 836}
+};
+
+XGI330_CHTVDataStruct  XGI_CHTVOPALData[]=
+{
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {840, 625, 840, 625},
+ {960, 750, 960, 750}
+};
+
+XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_1_H[]=
+{
+               /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                {{      0x4B,0x27,0x8F,0x32,0x1B,0x00,0x45,0x00 }}, /* 00 (320x) */
+                {{      0x4B,0x27,0x8F,0x2B,0x03,0x00,0x44,0x00 }}, /* 01 (360x) */
+                {{      0x55,0x31,0x99,0x46,0x1D,0x00,0x55,0x00 }}, /* 02 (400x) */
+                {{      0x63,0x3F,0x87,0x4A,0x93,0x00,0x01,0x00 }}, /* 03 (512x) */
+                {{      0x73,0x4F,0x97,0x55,0x86,0x00,0x05,0x00 }}, /* 04 (640x) */
+                {{      0x73,0x4F,0x97,0x55,0x86,0x00,0x05,0x00 }}, /* 05 (720x) */
+                {{      0x87,0x63,0x8B,0x69,0x1A,0x00,0x26,0x00 }}, /* 06 (800x) */
+                {{      0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* 07 (1024x) */
+};
+
+XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_1_H[]=
+{
+               /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                {{      0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }}, /* 00 (320x) */
+                {{      0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }}, /* 01 (360x) */
+                {{      0x60,0x31,0x84,0x3A,0x88,0x00,0x01,0x00 }}, /* 02 (400x) */
+                {{      0x6E,0x3F,0x92,0x48,0x96,0x00,0x01,0x00 }}, /* 03 (512x) */
+                {{      0x7E,0x4F,0x82,0x58,0x06,0x00,0x06,0x00 }}, /* 04 (640x) */
+                {{      0x7E,0x4F,0x82,0x58,0x06,0x00,0x06,0x00 }}, /* 05 (720x) */
+                {{      0x92,0x63,0x96,0x6C,0x1A,0x00,0x06,0x00 }}, /* 06 (800x) */
+                {{      0xAE,0x7F,0x92,0x88,0x96,0x00,0x02,0x00 }}, /* 07 (1024x) */
+                {{      0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* 08 (1280x) */
+};
+
+XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_2_H[]=
+{
+               /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                {{      0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }}, /* 00 (320x) */
+                {{      0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }}, /* 01 (360x) */
+                {{      0x63,0x31,0x87,0x3D,0x8E,0x00,0x01,0x00 }}, /* 02 (400x) */
+                {{      0x63,0x3F,0x87,0x45,0x96,0x00,0x01,0x00 }}, /* 03 (512x) */
+                {{      0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }}, /* 04 (640x) */
+                {{      0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }}, /* 05 (720x) */
+                {{      0xA3,0x63,0x87,0x78,0x89,0x00,0x02,0x00 }}, /* 06 (800x) */
+                {{      0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* 07 (1024x) */
+};
+
+XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_2_H[]=
+{
+                /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                {{      0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }}, /* 00 (320x) */
+                {{      0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }}, /* 01 (360x) */
+                {{      0x7E,0x40,0x84,0x49,0x91,0x00,0x01,0x00 }}, /* 02 (400x) */
+                {{      0x7E,0x47,0x93,0x50,0x9E,0x00,0x01,0x00 }}, /* 03 (512x) */
+                {{      0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }}, /* 04 (640x) */
+                {{      0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }}, /* 05 (720x) */
+                {{      0xCE,0x81,0x94,0x8A,0x98,0x00,0x02,0x00 }}, /* 06 (800x) */
+                {{      0xCE,0x8F,0x82,0x98,0x06,0x00,0x07,0x00 }}, /* 07 (1024x) */
+                {{      0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* 08 (1280x) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_1_H[]=
+{               /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                {{      0x47,0x27,0x8B,0x2C,0x1A,0x00,0x05,0x00 }}, /* 00 (320x) */
+                {{      0x47,0x27,0x8B,0x30,0x1E,0x00,0x05,0x00 }}, /* 01 (360x) */
+                {{      0x51,0x31,0x95,0x36,0x04,0x00,0x01,0x00 }}, /* 02 (400x) */
+                {{      0x5F,0x3F,0x83,0x44,0x92,0x00,0x01,0x00 }}, /* 03 (512x) */
+                {{      0x6F,0x4F,0x93,0x54,0x82,0x00,0x05,0x00 }}, /* 04 (640x) */
+                {{      0x6F,0x4F,0x93,0x54,0x82,0x00,0x05,0x00 }}, /* 05 (720x) */
+                {{      0x83,0x63,0x87,0x68,0x16,0x00,0x06,0x00 }}, /* 06 (800x) */
+                {{      0x9F,0x7F,0x83,0x84,0x92,0x00,0x02,0x00 }}, /* 07 (1024x) */
+                {{      0xBF,0x9F,0x83,0xA4,0x12,0x00,0x07,0x00 }}, /* 08 (1280x) */
+                {{      0xCE,0xAE,0x92,0xB3,0x01,0x00,0x03,0x00 }} /* 09 (1400x) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_2_H[]=
+{               /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                {{      0x76,0x3F,0x83,0x45,0x8C,0x00,0x41,0x00 }}, /* 00 (320x) */
+                {{      0x76,0x3F,0x83,0x45,0x8C,0x00,0x41,0x00 }}, /* 01 (360x) */
+                {{      0x76,0x31,0x9A,0x48,0x9F,0x00,0x41,0x00 }}, /* 02 (400x) */
+                {{      0x76,0x3F,0x9A,0x4F,0x96,0x00,0x41,0x00 }}, /* 03 (512x) */
+                {{      0xCE,0x7E,0x82,0x87,0x9E,0x00,0x02,0x00 }}, /* 04 (640x) */
+                {{      0xCE,0x7E,0x82,0x87,0x9E,0x00,0x02,0x00 }}, /* 05 (720x) */
+                {{      0xCE,0x63,0x92,0x96,0x04,0x00,0x07,0x00 }}, /* 06 (800x) */
+                {{      0xCE,0x7F,0x92,0xA4,0x12,0x00,0x07,0x00 }}, /* 07 (1024x) */
+                {{      0xCE,0x9F,0x92,0xB4,0x02,0x00,0x03,0x00 }}, /* 08 (1280x) */
+                {{      0xCE,0xAE,0x92,0xBC,0x0A,0x00,0x03,0x00 }} /* 09 (1400x) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11600x1200_1_H[]=
+/* ;302lv channelA [ycchen] 12/05/02 LCDHT=2048 */
+{   /* ; CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                {{      0x5B,0x27,0x9F,0x32,0x0A,0x00,0x01,0x00 }},/* 00 (320x) */
+                {{      0x5B,0x27,0x9F,0x32,0x0A,0x00,0x01,0x00 }},/* 01 (360x) */
+                {{      0x65,0x31,0x89,0x3C,0x94,0x00,0x01,0x00 }},/* 02 (400x) */
+                {{      0x73,0x3F,0x97,0x4A,0x82,0x00,0x05,0x00 }},/* 03 (512x) */
+                {{      0x83,0x4F,0x87,0x51,0x09,0x00,0x06,0x00 }},/* 04 (640x) */
+               {{      0x83,0x4F,0x87,0x51,0x09,0x00,0x06,0x00 }},/* 05 (720x) */
+               {{      0x97,0x63,0x9B,0x65,0x1D,0x00,0x06,0xF0 }},/* 06 (800x) */
+               {{      0xB3,0x7F,0x97,0x81,0x99,0x00,0x02,0x00 }},/* 07 (1024x) */
+               {{      0xD3,0x9F,0x97,0xA1,0x19,0x00,0x07,0x00 }},/* 08 (1280x) */
+               {{      0xE2,0xAE,0x86,0xB9,0x91,0x00,0x03,0x00 }},/* 09 (1400x) */
+               {{      0xFB,0xC7,0x9F,0xC9,0x81,0x00,0x07,0x00 }} /* 0A (1600x) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_V[]=
+{               /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
+                {{      0x97,0x1F,0x60,0x87,0x5D,0x83,0x10      }}, /* 00 (x350) */
+                {{      0xB4,0x1F,0x92,0x89,0x8F,0xB5,0x30      }}, /* 01 (x400) */
+                {{      0x04,0x3E,0xE2,0x89,0xDF,0x05,0x00      }}, /* 02 (x480) */
+                {{      0x7C,0xF0,0x5A,0x8F,0x57,0x7D,0xA0      }}, /* 03 (x600) */
+                {{      0x24,0xF5,0x02,0x88,0xFF,0x25,0x90      }} /* 04 (x768) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_V[]=
+{               /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+                {{      0x24,0xBB,0x31,0x87,0x5D,0x25,0x30      }}, /* 00 (x350) */
+                {{      0x24,0xBB,0x4A,0x80,0x8F,0x25,0x30      }}, /* 01 (x400) */
+                {{      0x24,0xBB,0x72,0x88,0xDF,0x25,0x30      }}, /* 02 (x480) */
+                {{      0x24,0xF1,0xAE,0x84,0x57,0x25,0xB0      }}, /* 03 (x600) */
+                {{      0x24,0xF5,0x02,0x88,0xFF,0x25,0x90      }} /* 04 (x768) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_V[]=
+{               /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+                {{       0x86,0x1F,0x5E,0x82,0x5D,0x87,0x00     }}, /* 00 (x350) */
+                {{       0xB8,0x1F,0x90,0x84,0x8F,0xB9,0x30     }}, /* 01 (x400) */
+                {{       0x08,0x3E,0xE0,0x84,0xDF,0x09,0x00     }}, /* 02 (x480) */
+                {{       0x80,0xF0,0x58,0x8C,0x57,0x81,0xA0     }}, /* 03 (x600) */
+                {{       0x28,0xF5,0x00,0x84,0xFF,0x29,0x90     }}, /* 04 (x768) */
+                {{       0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9     }} /* 05 (x1024) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_V[]=
+{               /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+                {{      0x28,0xD2,0xAF,0x83,0xAE,0xD8,0xA1      }}, /* 00 (x350) */
+                {{      0x28,0xD2,0xC8,0x8C,0xC7,0xF2,0x81      }}, /* 01 (x400) */
+                {{      0x28,0xD2,0xF0,0x84,0xEF,0x1A,0xB1      }}, /* 02 (x480) */
+                {{      0x28,0xDE,0x2C,0x8F,0x2B,0x56,0x91      }}, /* 03 (x600) */
+                {{      0x28,0xDE,0x80,0x83,0x7F,0xAA,0x91      }}, /* 04 (x768) */
+                {{      0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9      }} /* 05 (x1024) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_1_V[]=
+{               /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+                {{      0x6C,0x1F,0x60,0x84,0x5D,0x6D,0x10      }}, /* 00 (x350) */
+                {{      0x9E,0x1F,0x93,0x86,0x8F,0x9F,0x30      }}, /* 01 (x400) */
+                {{      0xEE,0x1F,0xE2,0x86,0xDF,0xEF,0x10      }}, /* 02 (x480) */
+                {{      0x66,0xF0,0x5A,0x8e,0x57,0x67,0xA0      }}, /* 03 (x600) */
+                {{      0x0E,0xF5,0x02,0x86,0xFF,0x0F,0x90      }}, /* 04 (x768) */
+                {{      0x0E,0x5A,0x02,0x86,0xFF,0x0F,0x89      }}, /* 05 (x1024) */
+                {{      0x28,0x10,0x1A,0x80,0x19,0x29,0x0F      }} /* 06 (x1050) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_2_V[]=
+{              /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+                {{      0x28,0x92,0xB6,0x83,0xB5,0xCF,0x81      }}, /* 00 (x350) */
+                {{      0x28,0x92,0xD5,0x82,0xD4,0xEE,0x81      }}, /* 01 (x400) */
+                {{      0x28,0x92,0xFD,0x8A,0xFC,0x16,0xB1      }}, /* 02 (x480) */
+                {{      0x28,0xD4,0x39,0x86,0x57,0x29,0x81      }}, /* 03 (x600) */
+                {{      0x28,0xD4,0x8D,0x9A,0xFF,0x29,0xA1      }}, /* 04 (x768) */
+                {{      0x28,0x5A,0x0D,0x9A,0xFF,0x29,0xA9      }}, /* 05 (x1024) */
+                {{      0x28,0x10,0x1A,0x87,0x19,0x29,0x8F      }} /* 06 (x1050) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11600x1200_1_V[]=
+{
+               /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
+                {{      0xd4,0x1F,0x81,0x84,0x5D,0xd5,0x10      }}, /* 00 (x350) */
+                {{      0x06,0x3e,0xb3,0x86,0x8F,0x07,0x20      }}, /* 01 (x400) */
+                {{      0x56,0xba,0x03,0x86,0xDF,0x57,0x00      }}, /* 02 (x480) */
+                {{      0xce,0xF0,0x7b,0x8e,0x57,0xcf,0xa0      }}, /* 03 (x600) */
+                {{      0x76,0xF5,0x23,0x86,0xFF,0x77,0x90      }}, /* 04 (x768) */
+                {{      0x76,0x5A,0x23,0x86,0xFF,0x77,0x89      }}, /* 05 (x1024) */
+                {{      0x90,0x10,0x1A,0x8E,0x19,0x91,0x2F      }}, /* 06 (x1050) */
+                {{      0x26,0x11,0xd3,0x86,0xaF,0x27,0x3f      }} /* 07 (x1200) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_Hx75[]=
+{      /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+    {{      0x4B,0x27,0x8F,0x32,0x1B,0x00,0x45,0x00 }},/* ; 00 (320x) */
+    {{      0x4B,0x27,0x8F,0x2B,0x03,0x00,0x44,0x00 }},/* ; 01 (360x) */
+    {{      0x55,0x31,0x99,0x46,0x1D,0x00,0x55,0x00 }},/* ; 02 (400x) */
+    {{      0x63,0x3F,0x87,0x4A,0x93,0x00,0x01,0x00 }},/* ; 03 (512x) */
+    {{      0x6F,0x4F,0x93,0x54,0x80,0x00,0x05,0x00 }},/* ; 04 (640x) */
+    {{      0x6F,0x4F,0x93,0x54,0x80,0x00,0x05,0x00 }},/* ; 05 (720x) */
+    {{      0x83,0x63,0x87,0x68,0x14,0x00,0x26,0x00 }},/* ; 06 (800x) */
+    {{      0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00 }} /* ; 07 (1024x) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_Vx75[]=
+{      /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
+    {{      0x97,0x1F,0x60,0x87,0x5D,0x83,0x10      }},/* ; 00 (x350) */
+    {{      0xB4,0x1F,0x92,0x89,0x8F,0xB5,0x30      }},/* ; 01 (x400) */
+    {{      0xFE,0x1F,0xE0,0x84,0xDF,0xFF,0x10      }},/* ; 02 (x480) */
+    {{      0x76,0xF0,0x58,0x8C,0x57,0x77,0xA0      }},/* ; 03 (x600) */
+    {{      0x1E,0xF5,0x00,0x83,0xFF,0x1F,0x90      }} /* ; 04 (x768) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_Hx75[]=
+{       /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+    {{      0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }},/* ; 00 (320x) */
+    {{      0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }},/* ; 01 (360x) */
+    {{      0x63,0x31,0x87,0x3D,0x8E,0x00,0x01,0x00 }},/* ; 02 (400x) */
+    {{      0x63,0x3F,0x87,0x45,0x96,0x00,0x01,0x00 }},/* ; 03 (512x) */
+    {{      0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }},/* ; 04 (640x) */
+    {{      0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }},/* ; 05 (720x) */
+    {{      0xA3,0x63,0x87,0x78,0x89,0x00,0x02,0x00 }},/* ; 06 (800x) */
+    {{      0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* ; 07 (1024x) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_Vx75[]=
+{       /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+    {{      0x24,0xBB,0x31,0x87,0x5D,0x25,0x30      }},/* ; 00 (x350) */
+    {{      0x24,0xBB,0x4A,0x80,0x8F,0x25,0x30      }},/* ; 01 (x400) */
+    {{      0x24,0xBB,0x72,0x88,0xDF,0x25,0x30      }},/* ; 02 (x480) */
+    {{      0x24,0xF1,0xAE,0x84,0x57,0x25,0xB0      }},/* ; 03 (x600) */
+    {{      0x24,0xF5,0x02,0x88,0xFF,0x25,0x90      }} /* ; 04 (x768) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_Hx75[]=
+{      /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+    {{      0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }},/* ; 00 (320x) */
+    {{      0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }},/* ; 01 (360x) */
+    {{      0x60,0x31,0x84,0x3A,0x88,0x00,0x01,0x00 }},/* ; 02 (400x) */
+    {{      0x6E,0x3F,0x92,0x48,0x96,0x00,0x01,0x00 }},/* ; 03 (512x) */
+    {{      0x7E,0x4F,0x82,0x54,0x06,0x00,0x06,0x00 }},/* ; 04 (640x) */
+    {{      0x7E,0x4F,0x82,0x54,0x06,0x00,0x06,0x00 }},/* ; 05 (720x) */
+    {{      0x92,0x63,0x96,0x68,0x1A,0x00,0x06,0x00 }},/* ; 06 (800x) */
+    {{      0xAE,0x7F,0x92,0x84,0x96,0x00,0x02,0x00 }},/* ; 07 (1024x) */
+    {{      0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00 }} /* ; 08 (1280x) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_Vx75[]=
+{      /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+    {{      0x86,0xD1,0xBC,0x80,0xBB,0xE5,0x00      }},/* ; 00 (x350) */
+    {{      0xB8,0x1F,0x90,0x84,0x8F,0xB9,0x30      }},/* ; 01 (x400) */
+    {{      0x08,0x3E,0xE0,0x84,0xDF,0x09,0x00      }},/* ; 02 (x480) */
+    {{      0x80,0xF0,0x58,0x8C,0x57,0x81,0xA0      }},/* ; 03 (x600) */
+    {{      0x28,0xF5,0x00,0x84,0xFF,0x29,0x90      }},/* ; 04 (x768) */
+    {{      0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9      }} /* ; 05 (x1024) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_Hx75[]=
+{
+       /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+    {{      0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }},/* ; 00 (320x) */
+    {{      0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }},/* ; 01 (360x) */
+    {{      0x7E,0x40,0x84,0x49,0x91,0x00,0x01,0x00 }},/* ; 02 (400x) */
+    {{      0x7E,0x47,0x93,0x50,0x9E,0x00,0x01,0x00 }},/* ; 03 (512x) */
+    {{      0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }},/* ; 04 (640x) */
+    {{      0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }},/* ; 05 (720x) */
+    {{      0xCE,0x81,0x94,0x8A,0x98,0x00,0x02,0x00 }},/* ; 06 (800x) */
+    {{      0xCE,0x8F,0x82,0x98,0x06,0x00,0x07,0x00 }},/* ; 07 (1024x) */
+    {{      0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* ; 08 (1280x) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[]=
+{
+        /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+     {{     0x28,0xD2,0xAF,0x83,0xAE,0xD8,0xA1     }},/* ; 00 (x350) */
+     {{     0x28,0xD2,0xC8,0x8C,0xC7,0xF2,0x81     }},/* ; 01 (x400) */
+     {{     0x28,0xD2,0xF0,0x84,0xEF,0x1A,0xB1     }},/* ; 02 (x480) */
+     {{     0x28,0xDE,0x2C,0x8F,0x2B,0x56,0x91     }},/* ; 03 (x600) */
+     {{     0x28,0xDE,0x80,0x83,0x7F,0xAA,0x91     }},/* ; 04 (x768) */
+     {{     0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9     }} /* ; 05 (x1024) */
+};
+
+XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1UNTSC[]=
+{
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+    0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+    0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+    0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+    0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,0x00 }},
+ {{0x5d,0x4f,0x81,0x53,0x9c,0x56,0xba,
+    0x18,0x84,0xdf,0x57,0x00,0x00,0x01,0x00 }},
+ {{0x80,0x63,0x84,0x6c,0x17,0xec,0xf0,
+   0x90,0x8c,0x57,0xed,0x20,0x00,0x06,0x01 }}
+};
+
+XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1ONTSC[]=
+{
+ {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+    0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+    0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+    0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+    0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,0x00 }},
+ {{0x5d,0x4f,0x81,0x56,0x9c,0x0b,0x3e,
+    0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01,0x00 }},
+ {{0x7d,0x63,0x81,0x6a,0x16,0xba,0xf0,
+   0x7f,0x86,0x57,0xbb,0x00,0x00,0x06,0x01 }}
+};
+
+XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1UPAL[]=
+{
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+    0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+    0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+    0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+    0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
+ {{0x64,0x4f,0x88,0x55,0x80,0xec,0xba,
+    0x50,0x84,0xdf,0xed,0x00,0x00,0x05,0x00 }},
+ {{0x70,0x63,0x94,0x68,0x8d,0x42,0xf1,
+   0xc8,0x8c,0x57,0xe9,0x20,0x00,0x05,0x01 }}
+};
+
+XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1OPAL[]=
+{
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+    0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+    0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+    0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+    0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
+ {{0x64,0x4f,0x88,0x55,0x80,0x6f,0xba,
+    0x20,0x83,0xdf,0x70,0x00,0x00,0x05,0x00 }},
+ {{0x73,0x63,0x97,0x69,0x8e,0xec,0xf0,
+   0x90,0x8c,0x57,0xed,0x20,0x00,0x05,0x01 }}
+};
+
+/*add for new UNIVGABIOS*/
+XGI330_LCDDataTablStruct XGI_LCDDataTable[]=
+{
+  {Panel1024x768,0x0019,0x0001,0},  /* XGI_ExtLCD1024x768Data */
+  {Panel1024x768,0x0019,0x0000,1},  /* XGI_StLCD1024x768Data */
+  {Panel1024x768,0x0018,0x0010,2},  /* XGI_CetLCD1024x768Data */
+  {Panel1280x1024,0x0019,0x0001,3},  /* XGI_ExtLCD1280x1024Data */
+  {Panel1280x1024,0x0019,0x0000,4},  /* XGI_StLCD1280x1024Data */
+  {Panel1280x1024,0x0018,0x0010,5},  /* XGI_CetLCD1280x1024Data */
+  {Panel1400x1050,0x0019,0x0001,6},  /* XGI_ExtLCD1400x1050Data */
+  {Panel1400x1050,0x0019,0x0000,7},  /* XGI_StLCD1400x1050Data */
+  {Panel1400x1050,0x0018,0x0010,8},  /* XGI_CetLCD1400x1050Data */
+  {Panel1600x1200,0x0019,0x0001,9},   /* XGI_ExtLCD1600x1200Data */
+  {Panel1600x1200,0x0019,0x0000,10},  /* XGI_StLCD1600x1200Data */
+  {PanelRef60Hz,0x0008,0x0008,11},     /* XGI_NoScalingData */
+  {Panel1024x768x75,0x0019,0x0001,12},         /* XGI_ExtLCD1024x768x75Data */
+  {Panel1024x768x75,0x0019,0x0000,13},         /* XGI_StLCD1024x768x75Data */
+  {Panel1024x768x75,0x0018,0x0010,14},         /* XGI_CetLCD1024x768x75Data */
+  {Panel1280x1024x75,0x0019,0x0001,15}, /* XGI_ExtLCD1280x1024x75Data */
+  {Panel1280x1024x75,0x0019,0x0000,16}, /* XGI_StLCD1280x1024x75Data */
+  {Panel1280x1024x75,0x0018,0x0010,17}, /* XGI_CetLCD1280x1024x75Data */
+  {PanelRef75Hz,0x0008,0x0008,18},     /* XGI_NoScalingDatax75 */
+  {0xFF,0x0000,0x0000,0}               /* End of table */
+};
+
+XGI330_LCDDataTablStruct XGI_LCDDesDataTable[]=
+{
+  {Panel1024x768,0x0019,0x0001,0}, /* XGI_ExtLCDDes1024x768Data */
+  {Panel1024x768,0x0019,0x0000,1}, /* XGI_StLCDDes1024x768Data */
+  {Panel1024x768,0x0018,0x0010,2}, /* XGI_CetLCDDes1024x768Data */
+  {Panel1280x1024,0x0019,0x0001,3}, /* XGI_ExtLCDDes1280x1024Data */
+  {Panel1280x1024,0x0019,0x0000,4}, /* XGI_StLCDDes1280x1024Data */
+  {Panel1280x1024,0x0018,0x0010,5}, /* XGI_CetLCDDes1280x1024Data */
+  {Panel1400x1050,0x0019,0x0001,6}, /* XGI_ExtLCDDes1400x1050Data */
+  {Panel1400x1050,0x0019,0x0000,7}, /* XGI_StLCDDes1400x1050Data */
+  {Panel1400x1050,0x0418,0x0010,8}, /* XGI_CetLCDDes1400x1050Data */
+  {Panel1400x1050,0x0418,0x0410,9}, /* XGI_CetLCDDes1400x1050Data2 */
+  {Panel1600x1200,0x0019,0x0001,10}, /* XGI_ExtLCDDes1600x1200Data */
+  {Panel1600x1200,0x0019,0x0000,11}, /* XGI_StLCDDes1600x1200Data */
+  {PanelRef60Hz,0x0008,0x0008,12},     /* XGI_NoScalingDesData */
+  {Panel1024x768x75,0x0019,0x0001,13},         /* XGI_ExtLCDDes1024x768x75Data */
+  {Panel1024x768x75,0x0019,0x0000,14}, /* XGI_StLCDDes1024x768x75Data */
+  {Panel1024x768x75,0x0018,0x0010,15},  /* XGI_CetLCDDes1024x768x75Data */
+  {Panel1280x1024x75,0x0019,0x0001,16},        /* XGI_ExtLCDDes1280x1024x75Data */
+  {Panel1280x1024x75,0x0019,0x0000,17}, /* XGI_StLCDDes1280x1024x75Data */
+  {Panel1280x1024x75,0x0018,0x0010,18},        /* XGI_CetLCDDes1280x1024x75Data */
+  {PanelRef75Hz,0x0008,0x0008,19},     /* XGI_NoScalingDesDatax75 */
+  {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_H[]=
+{
+  {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDSCRT11024x768_1_H */
+  {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDSCRT11024x768_2_H */
+  {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDSCRT11280x1024_1_H */
+  {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDSCRT11280x1024_2_H */
+  {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDSCRT11400x1050_1_H */
+  {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDSCRT11400x1050_2_H */
+  {Panel1600x1200,0x0018,0x0000,6},  /* XGI_LVDSCRT11600x1200_1_H */
+  {Panel1024x768x75,0x0018,0x0000,7},  /* XGI_LVDSCRT11024x768_1_Hx75 */
+  {Panel1024x768x75,0x0018,0x0010,8},  /* XGI_LVDSCRT11024x768_2_Hx75 */
+  {Panel1280x1024x75,0x0018,0x0000,9}, /* XGI_LVDSCRT11280x1024_1_Hx75 */
+  {Panel1280x1024x75,0x0018,0x0010,10},        /* XGI_LVDSCRT11280x1024_2_Hx75 */
+  {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_V[]=
+{
+  {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDSCRT11024x768_1_V */
+  {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDSCRT11024x768_2_V */
+  {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDSCRT11280x1024_1_V */
+  {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDSCRT11280x1024_2_V */
+  {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDSCRT11400x1050_1_V */
+  {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDSCRT11400x1050_2_V */
+  {Panel1600x1200,0x0018,0x0000,6}, /* XGI_LVDSCRT11600x1200_1_V */
+  {Panel1024x768x75,0x0018,0x0000,7},  /* XGI_LVDSCRT11024x768_1_Vx75 */
+  {Panel1024x768x75,0x0018,0x0010,8},  /* XGI_LVDSCRT11024x768_2_Vx75 */
+  {Panel1280x1024x75,0x0018,0x0000,9}, /* XGI_LVDSCRT11280x1024_1_Vx75 */
+  {Panel1280x1024x75,0x0018,0x0010,10},        /* XGI_LVDSCRT11280x1024_2_Vx75 */
+  {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[]=
+{
+  {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDS1024x768Data_1 */
+  {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDS1024x768Data_2 */
+  {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDS1280x1024Data_1 */
+  {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDS1280x1024Data_2 */
+  {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDS1400x1050Data_1 */
+  {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDS1400x1050Data_2 */
+  {Panel1600x1200,0x0018,0x0000,6}, /* XGI_LVDS1600x1200Data_1 */
+  {PanelRef60Hz,0x0008,0x0008,7}, /* XGI_LVDSNoScalingData */
+  {Panel1024x768x75,0x0018,0x0000,8},  /* XGI_LVDS1024x768Data_1x75 */
+  {Panel1024x768x75,0x0018,0x0010,9},  /* XGI_LVDS1024x768Data_2x75 */
+  {Panel1280x1024x75,0x0018,0x0000,10},        /* XGI_LVDS1280x1024Data_1x75 */
+  {Panel1280x1024x75,0x0018,0x0010,11}, /* XGI_LVDS1280x1024Data_2x75 */
+  {PanelRef75Hz,0x0008,0x0008,12},     /* XGI_LVDSNoScalingDatax75 */
+  {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[]=
+{
+  {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDS1024x768Des_1 */
+  {Panel1024x768,0x0618,0x0410,1}, /* XGI_LVDS1024x768Des_3 */
+  {Panel1024x768,0x0018,0x0010,2}, /* XGI_LVDS1024x768Des_2 */
+  {Panel1280x1024,0x0018,0x0000,3}, /* XGI_LVDS1280x1024Des_1 */
+  {Panel1280x1024,0x0018,0x0010,4}, /* XGI_LVDS1280x1024Des_2 */
+  {Panel1400x1050,0x0018,0x0000,5}, /* XGI_LVDS1400x1050Des_1 */
+  {Panel1400x1050,0x0018,0x0010,6}, /* XGI_LVDS1400x1050Des_2 */
+  {Panel1600x1200,0x0018,0x0000,7}, /* XGI_LVDS1600x1200Des_1 */
+  {PanelRef60Hz,0x0008,0x0008,8},      /* XGI_LVDSNoScalingDesData */
+  {Panel1024x768x75,0x0018,0x0000,9},  /* XGI_LVDS1024x768Des_1x75 */
+  {Panel1024x768x75,0x0618,0x0410,10}, /* XGI_LVDS1024x768Des_3x75 */
+  {Panel1024x768x75,0x0018,0x0010,11}, /* XGI_LVDS1024x768Des_2x75 */
+  {Panel1280x1024x75,0x0018,0x0000,12},        /* XGI_LVDS1280x1024Des_1x75 */
+  {Panel1280x1024x75,0x0018,0x0010,13},        /* XGI_LVDS1280x1024Des_2x75 */
+  {PanelRef75Hz,0x0008,0x0008,14},     /* XGI_LVDSNoScalingDesDatax75 */
+  {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_LCDDataTablStruct XGI_EPLCHLCDRegPtr[]=
+{
+  {Panel1024x768,0x0000,0x0000,0}, /* XGI_CH7017LV1024x768 */
+  {Panel1400x1050,0x0000,0x0000,1}, /* XGI_CH7017LV1400x1050 */
+  {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_TVDataTablStruct XGI_TVDataTable[]=
+{
+ {0x09E1,0x0001,0},    /* XGI_ExtPALData */
+ {0x09E1,0x0000,1},    /* XGI_ExtNTSCData */
+ {0x09E1,0x0801,2},    /* XGI_StPALData */
+ {0x09E1,0x0800,3},    /* XGI_StNTSCData */
+ {0x49E0,0x0100,4},    /* XGI_ExtHiTVData */
+ {0x49E0,0x4100,5},    /* XGI_St2HiTVData */
+ {0x49E0,0x4900,13},   /* XGI_St1HiTVData */
+ {0x09E0,0x0020,6},    /* XGI_ExtYPbPr525iData */
+ {0x09E0,0x0040,7},    /* XGI_ExtYPbPr525pData */
+ {0x09E0,0x0080,8},    /* XGI_ExtYPbPr750pData */
+ {0x09E0,0x0820,9},    /* XGI_StYPbPr525iData */
+ {0x09E0,0x0840,10},   /* XGI_StYPbPr525pData */
+ {0x09E0,0x0880,11},   /* XGI_StYPbPr750pData */
+ {0xffff,0x0000,12}    /* END */
+};
+
+USHORT TVLenList[]=
+{
+   LVDSCRT1Len_H,
+   LVDSCRT1Len_V,
+   LVDSDataLen,
+   0,
+   TVDataLen,
+   0,
+   0,
+   CHTVRegLen
+} ;
+
+/* Chrontel 7017 TV CRT1 Timing List */
+XGI330_TVDataTablStruct XGI_EPLCHTVCRT1Ptr[]=
+{
+  {0x0011,0x0000,0}, /* XGI_CHTVCRT1UNTSC */
+  {0x0011,0x0010,1}, /* XGI_CHTVCRT1ONTSC */
+  {0x0011,0x0001,2}, /* XGI_CHTVCRT1UPAL */
+  {0x0011,0x0011,3}, /* XGI_CHTVCRT1OPAL */
+  {0xFFFF,0x0000,4}
+};
+
+/* ;;Chrontel 7017 TV Timing List */
+XGI330_TVDataTablStruct XGI_EPLCHTVDataPtr[]=
+{
+  {0x0011,0x0000,0}, /* XGI_CHTVUNTSCData */
+  {0x0011,0x0010,1}, /* XGI_CHTVONTSCData */
+  {0x0011,0x0001,2}, /* XGI_CHTVUPALData */
+  {0x0011,0x0011,3}, /* XGI_CHTVOPALData */
+  {0xFFFF,0x0000,4}
+};
+
+/* ;;Chrontel 7017 TV Reg. List */
+XGI330_TVDataTablStruct XGI_EPLCHTVRegPtr[]=
+{
+  {0x0011,0x0000,0}, /* XGI_CHTVRegUNTSC */
+  {0x0011,0x0010,1}, /* XGI_CHTVRegONTSC */
+  {0x0011,0x0001,2}, /* XGI_CHTVRegUPAL */
+  {0x0011,0x0011,3}, /* XGI_CHTVRegOPAL */
+  {0xFFFF,0x0000,4}
+};
+
+USHORT LCDLenList[]=
+{
+   LVDSCRT1Len_H,
+   LVDSCRT1Len_V,
+   LVDSDataLen,
+   LCDDesDataLen,
+   LCDDataLen,
+   LCDDesDataLen,
+   0,
+   LCDDesDataLen,
+   LCDDesDataLen,
+   0
+} ;
+
+XGI330_LCDCapStruct  XGI660_LCDDLCapList[]=  /* 660, Dual link */
+{
+/* LCDCap1024x768 */
+               {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65,
+                0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024 */
+                {Panel1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
+                0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1400x1050 */
+                {Panel1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
+                0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1600x1200 */
+                {Panel1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, 0x053, 0xC0, 0x03, VCLK162,
+                0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1024x768x75 */
+               {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75,
+                0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024x75 */
+                {Panel1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x90, 0x03, VCLK135_5,
+                0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCapDefault */
+                {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65,
+               0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+               0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+};
+
+XGI330_LCDCapStruct  XGI_LCDDLCapList[]=  /* Dual link only */
+{
+/* LCDCap1024x768 */
+               {Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
+               0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+               0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024 */
+               {Panel1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
+               0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+               0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1400x1050 */
+               {Panel1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
+                0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1600x1200 */
+               {Panel1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, 0x012, 0xC0, 0x03, VCLK162,
+                0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1024x768x75 */
+               {Panel1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75,
+                0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024x75 */
+               {Panel1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x90, 0x03, VCLK135_5,
+                0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCapDefault */
+               {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
+               0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+               0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+};
+
+XGI330_LCDCapStruct  XGI660_LCDCapList[]=
+{
+/* LCDCap1024x768 */
+                {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65,
+               0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+               0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024 */
+                {Panel1280x1024, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
+               0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+               0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1400x1050 */
+                {Panel1400x1050, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
+                0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1600x1200 */
+                {Panel1600x1200, DefaultLCDCap, LCDToFull, 0x053, 0xC0, 0x03, VCLK162,
+                0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1024x768x75 */
+               {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75,
+                0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024x75 */
+                {Panel1280x1024x75,+DefaultLCDCap, StLCDBToA, 0x053, 0x90, 0x03, VCLK135_5,
+                0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCapDefault */
+                {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65,
+               0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+               0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+};
+
+XGI330_LCDCapStruct  XGI_LCDCapList[]=
+{
+/* LCDCap1024x768 */
+               {Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
+               0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+               0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024 */
+               {Panel1280x1024, DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
+               0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+               0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1400x1050 */
+               {Panel1400x1050, DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
+                0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1600x1200 */
+               {Panel1600x1200, DefaultLCDCap, LCDToFull, 0x012, 0xC0, 0x03, VCLK162,
+                0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1024x768x75 */
+               {Panel1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75,
+                0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024x75 */
+               {Panel1280x1024x75, DefaultLCDCap, StLCDBToA, 0x012, 0x90, 0x03, VCLK135_5,
+                0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+                0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCapDefault */
+               {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
+               0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+               0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+};
+
+XGI21_LVDSCapStruct XGI21_LCDCapList[]=
+{
+    {DisableLCD24bpp + LCDPolarity,
+     2160,1250,1600,1200,  64,  1,  192,   3,
+     0x70,0x24,0x20,0x04,0x0A,0x02,0xC8
+    },
+    {DisableLCD24bpp + LCDPolarity,
+     1688,1066,1280,1024,  48,  1,  112,   3,
+     0x70,0x44,0x20,0x04,0x0A,0x02,0xC8
+    },
+    {DisableLCD24bpp + LCDPolarity + (LCDPolarity << 8),
+     1344, 806,1024, 768,  24,  3,  136,   6,
+     0x6C,0x65,0x20,0x04,0x0A,0x02,0xC8
+    },
+    {DisableLCD24bpp + LCDPolarity,
+     1056, 628, 800, 600,  40,   1, 128,   4,
+     0x42,0xE2,0x20,0x14,0x0A,0x02,0x00
+    },
+    {DisableLCD24bpp + LCDPolarity,
+      928, 525, 800, 480,  40,  13,  48,   3,
+     0x52,0xC5,0x20,0x14,0x0A,0x02,0x00
+    },
+    {DisableLCD24bpp + LCDPolarity + (LCDPolarity << 8),
+      800, 525, 640, 480,  16,  10,  96,   2,
+     0x1B,0xE1,0x20,0x04,0x0A,0x02,0xC8
+    }
+
+};
+
+XGI_Ext2Struct XGI330_RefIndex[]=
+{
+{Support32Bpp + SupportAllCRT2 + SyncPN,                       RES320x200,      VCLK25_175, 0x00,0x10,0x59, 320, 200},/* 00 */
+{Support32Bpp + SupportAllCRT2 + SyncPN,                       RES320x200,      VCLK25_175, 0x00,0x10,0x00, 320, 400},/* 01 */
+{Support32Bpp + SupportAllCRT2 + SyncNN,                       RES320x240,      VCLK25_175, 0x04,0x20,0x50, 320, 240},/* 02 */
+{Support32Bpp + SupportAllCRT2 + SyncPP,                       RES400x300,      VCLK40,     0x05,0x32,0x51, 400, 300},/* 03 */
+{Support32Bpp + NoSupportTV + SyncNN + SupportTV1024,          RES512x384,      VCLK65,     0x06,0x43,0x52, 512, 384},/* 04 */
+{Support32Bpp + SupportAllCRT2 + SyncPN,                       RES640x400,      VCLK25_175, 0x00,0x14,0x2f, 640, 400},/* 05 */
+{Support32Bpp + SupportAllCRT2 + SyncNN,                       RES640x480x60,   VCLK25_175, 0x04,0x24,0x2e, 640, 480},/* 06 640x480x60Hz (LCD 640x480x60z) */
+{Support32Bpp + NoSupportHiVisionTV + SyncNN,                  RES640x480x72,   VCLK31_5,   0x04,0x24,0x2e, 640, 480},/* 07 640x480x72Hz (LCD 640x480x70Hz) */
+{Support32Bpp + NoSupportHiVisionTV + SyncNN,                  RES640x480x75,   VCLK31_5,   0x47,0x24,0x2e, 640, 480},/* 08 640x480x75Hz (LCD 640x480x75Hz) */
+{Support32Bpp + SupportRAMDAC2 + SyncNN,                       RES640x480x85,   VCLK36,     0x8A,0x24,0x2e, 640, 480},/* 09 640x480x85Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN,                       RES640x480x100,  VCLK43_163, 0x00,0x24,0x2e, 640, 480},/* 0a 640x480x100Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN,                       RES640x480x120,  VCLK52_406, 0x00,0x24,0x2e, 640, 480},/* 0b 640x480x120Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN,                       RES640x480x160,  VCLK72_852, 0x00,0x24,0x2e, 640, 480},/* 0c 640x480x160Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncNN,                       RES640x480x200,  VCLK86_6,   0x00,0x24,0x2e, 640, 480},/* 0d 640x480x200Hz */
+{Support32Bpp + NoSupportLCD + SyncPP,                         RES800x600x56,   VCLK36,     0x05,0x36,0x6a, 800, 600},/* 0e 800x600x56Hz */
+{Support32Bpp + NoSupportTV + SyncPP,                          RES800x600x60,   VCLK40,     0x05,0x36,0x6a, 800, 600},/* 0f 800x600x60Hz (LCD 800x600x60Hz) */
+{Support32Bpp + NoSupportHiVisionTV + SyncPP,                  RES800x600x72,   VCLK50,     0x48,0x36,0x6a, 800, 600},/* 10 800x600x72Hz (LCD 800x600x70Hz) */
+{Support32Bpp + NoSupportHiVisionTV + SyncPP,                  RES800x600x75,   VCLK49_5,   0x8B,0x36,0x6a, 800, 600},/* 11 800x600x75Hz (LCD 800x600x75Hz) */
+{Support32Bpp + SupportRAMDAC2 + SyncPP,                       RES800x600x85,   VCLK56_25,  0x00,0x36,0x6a, 800, 600},/* 12 800x600x85Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN,                       RES800x600x100,  VCLK68_179, 0x00,0x36,0x6a, 800, 600},/* 13 800x600x100Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN,                       RES800x600x120,  VCLK83_95,  0x00,0x36,0x6a, 800, 600},/* 14 800x600x120Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN,                       RES800x600x160,  VCLK116_406,0x00,0x36,0x6a, 800, 600},/* 15 800x600x160Hz */
+{Support32Bpp + InterlaceMode + SyncPP,                                RES1024x768x43,  VCLK44_9,   0x00,0x47,0x37,1024, 768},/* 16 1024x768x43Hz */
+{Support32Bpp + NoSupportTV + SyncNN + SupportTV1024,          RES1024x768x60,  VCLK65,     0x06,0x47,0x37,1024, 768},/* 17 1024x768x60Hz (LCD 1024x768x60Hz) */
+{Support32Bpp + NoSupportHiVisionTV + SyncNN,                  RES1024x768x70,  VCLK75,     0x49,0x47,0x37,1024, 768},/* 18 1024x768x70Hz (LCD 1024x768x70Hz) */
+{Support32Bpp + NoSupportHiVisionTV + SyncPP,                  RES1024x768x75,  VCLK78_75,  0x00,0x47,0x37,1024, 768},/* 19 1024x768x75Hz (LCD 1024x768x75Hz) */
+{Support32Bpp + SupportRAMDAC2 + SyncPP,                       RES1024x768x85,  VCLK94_5,   0x8C,0x47,0x37,1024, 768},/* 1a 1024x768x85Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN,                       RES1024x768x100, VCLK113_309,0x00,0x47,0x37,1024, 768},/* 1b 1024x768x100Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN,                       RES1024x768x120, VCLK139_054,0x00,0x47,0x37,1024, 768},/* 1c 1024x768x120Hz */
+{Support32Bpp + SupportLCD + SyncPP,                           RES1280x960x60,  VCLK108_2,  0x08,0x58,0x7b,1280, 960},/* 1d 1280x960x60Hz */
+{Support32Bpp + InterlaceMode + SyncPP,                                RES1280x1024x43, VCLK78_75,  0x00,0x58,0x3a,1280,1024},/* 1e 1280x1024x43Hz */
+{Support32Bpp + NoSupportTV + SyncPP,                          RES1280x1024x60, VCLK108_2,  0x07,0x58,0x3a,1280,1024},/* 1f 1280x1024x60Hz (LCD 1280x1024x60Hz) */
+{Support32Bpp + NoSupportTV + SyncPP,                          RES1280x1024x75, VCLK135_5,  0x00,0x58,0x3a,1280,1024},/* 20 1280x1024x75Hz (LCD 1280x1024x75Hz) */
+{Support32Bpp + SyncPP,                                                RES1280x1024x85, VCLK157_5,  0x00,0x58,0x3a,1280,1024},/* 21 1280x1024x85Hz */
+{Support32Bpp + SupportLCD + SyncPP + SupportCRT2in301C,       RES1600x1200x60, VCLK162,    0x09,0x7A,0x3c,1600,1200},/* 22 1600x1200x60Hz */
+{Support32Bpp + SyncPP + SupportCRT2in301C,                    RES1600x1200x65, VCLK175,    0x00,0x69,0x3c,1600,1200},/* 23 1600x1200x65Hz */
+{Support32Bpp + SyncPP + SupportCRT2in301C,                    RES1600x1200x70, VCLK189,    0x00,0x69,0x3c,1600,1200},/* 24 1600x1200x70Hz */
+{Support32Bpp + SyncPP + SupportCRT2in301C,                    RES1600x1200x75, VCLK202_5,  0x00,0x69,0x3c,1600,1200},/* 25 1600x1200x75Hz */
+{Support32Bpp + SyncPP,                                                RES1600x1200x85, VCLK229_5,  0x00,0x69,0x3c,1600,1200},/* 26 1600x1200x85Hz */
+{Support32Bpp + SyncPP,                                                RES1600x1200x100,VCLK269_655,0x00,0x69,0x3c,1600,1200},/* 27 1600x1200x100Hz */
+{Support32Bpp + SyncPP,                                                RES1600x1200x120,VCLK323_586,0x00,0x69,0x3c,1600,1200},/* 28 1600x1200x120Hz */
+{Support32Bpp + SupportLCD + SyncNP,                           RES1920x1440x60, VCLK234,    0x00,0x00,0x68,1920,1440},/* 29 1920x1440x60Hz */
+{Support32Bpp + SyncPN,                                                RES1920x1440x65, VCLK254_817,0x00,0x00,0x68,1920,1440},/* 2a 1920x1440x65Hz */
+{Support32Bpp + SyncPN,                                                RES1920x1440x70, VCLK277_015,0x00,0x00,0x68,1920,1440},/* 2b 1920x1440x70Hz */
+{Support32Bpp + SyncPN,                                                RES1920x1440x75, VCLK291_132,0x00,0x00,0x68,1920,1440},/* 2c 1920x1440x75Hz */
+{Support32Bpp + SyncPN,                                                RES1920x1440x85, VCLK330_615,0x00,0x00,0x68,1920,1440},/* 2d 1920x1440x85Hz */
+{Support16Bpp + SyncPN,                                                RES1920x1440x100,VCLK388_631,0x00,0x00,0x68,1920,1440},/* 2e 1920x1440x100Hz */
+{Support32Bpp + SupportLCD + SyncPN,                           RES2048x1536x60, VCLK266_952,0x00,0x00,0x6c,2048,1536},/* 2f 2048x1536x60Hz */
+{Support32Bpp + SyncPN,                                                RES2048x1536x65, VCLK291_766,0x00,0x00,0x6c,2048,1536},/* 30 2048x1536x65Hz */
+{Support32Bpp + SyncPN,                                                RES2048x1536x70, VCLK315_195,0x00,0x00,0x6c,2048,1536},/* 31 2048x1536x70Hz */
+{Support32Bpp + SyncPN,                                                RES2048x1536x75, VCLK340_477,0x00,0x00,0x6c,2048,1536},/* 32 2048x1536x75Hz */
+{Support16Bpp + SyncPN,                                                RES2048x1536x85, VCLK375_847,0x00,0x00,0x6c,2048,1536},/* 33 2048x1536x85Hz */
+{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr,    RES800x480x60,   VCLK39_77,  0x08,0x00,0x70, 800, 480},/* 34 800x480x60Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP,                       RES800x480x75,   VCLK49_5,   0x08,0x00,0x70, 800, 480},/* 35 800x480x75Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP,                       RES800x480x85,   VCLK56_25,  0x08,0x00,0x70, 800, 480},/* 36 800x480x85Hz */
+{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr,    RES1024x576x60,  VCLK65,     0x09,0x00,0x71,1024, 576},/* 37 1024x576x60Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP,                       RES1024x576x75,  VCLK78_75,  0x09,0x00,0x71,1024, 576},/* 38 1024x576x75Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP,                       RES1024x576x85,  VCLK94_5,   0x09,0x00,0x71,1024, 576},/* 39 1024x576x85Hz */
+{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr,    RES1280x720x60,  VCLK108_2,  0x0A,0x00,0x75,1280, 720},/* 3a 1280x720x60Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP,                       RES1280x720x75,  VCLK135_5,  0x0A,0x00,0x75,1280, 720},/* 3b 1280x720x75Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP,                       RES1280x720x85,  VCLK157_5,  0x0A,0x00,0x75,1280, 720},/* 3c 1280x720x85Hz */
+{Support32Bpp + SupportTV + SyncNN,                            RES720x480x60,   VCLK28_322, 0x06,0x00,0x31, 720, 480},/* 3d 720x480x60Hz */
+{Support32Bpp + SupportTV + SyncPP,                            RES720x576x56,   VCLK36,     0x06,0x00,0x32, 720, 576},/* 3e 720x576x56Hz */
+{Support32Bpp + InterlaceMode + NoSupportLCD + SyncPP,         RES856x480x79I,  VCLK35_2,   0x00,0x00,0x00, 856, 480},/* 3f 856x480x79I */
+{Support32Bpp + NoSupportLCD + SyncNN,                         RES856x480x60,   VCLK35_2,   0x00,0x00,0x00, 856, 480},/* 40 856x480x60Hz */
+{Support32Bpp + NoSupportHiVisionTV + SyncPP,                  RES1280x768x60,  VCLK79_411, 0x08,0x48,0x23,1280, 768},/* 41 1280x768x60Hz */
+{Support32Bpp + NoSupportHiVisionTV + SyncPP,                  RES1400x1050x60, VCLK122_61, 0x08,0x69,0x26,1400,1050},/* 42 1400x1050x60Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP,                       RES1152x864x60,  VCLK80_350, 0x37,0x00,0x20,1152, 864},/* 43 1152x864x60Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP,                       RES1152x864x75,  VCLK107_385,0x37,0x00,0x20,1152, 864},/* 44 1152x864x75Hz */
+{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP,          RES1280x960x75,  VCLK125_999,0x3A,0x88,0x7b,1280, 960},/* 45 1280x960x75Hz */
+{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP,          RES1280x960x85,  VCLK148_5,  0x0A,0x88,0x7b,1280, 960},/* 46 1280x960x85Hz */
+{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP,          RES1280x960x120, VCLK217_325,0x3A,0x88,0x7b,1280, 960},/* 47 1280x960x120Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN,                       RES1024x768x160, VCLK139_054,0x30,0x47,0x37,1024, 768},/* 48 1024x768x160Hz */
+};
+
+
+
+XGI330_VCLKDataStruct XGI330_VCLKData[]=
+{
+ { 0x1b,0xe1, 25}, /* 0x0 */
+ { 0x4e,0xe4, 28}, /* 0x1 */
+ { 0x57,0xe4, 31}, /* 0x2 */
+ { 0xc3,0xc8, 36}, /* 0x3 */
+ { 0x42,0xe2, 40}, /* 0x4 */
+ { 0xfe,0xcd, 43}, /* 0x5 */
+ { 0x5d,0xc4, 44}, /* 0x6 */
+ { 0x52,0xe2, 49}, /* 0x7 */
+ { 0x53,0xe2, 50}, /* 0x8 */
+ { 0x74,0x67, 52}, /* 0x9 */
+ { 0x6d,0x66, 56}, /* 0xa */
+ { 0x6c,0xc3, 65}, /* 0xb */
+ { 0x46,0x44, 67}, /* 0xc */
+ { 0xb1,0x46, 68}, /* 0xd */
+ { 0xd3,0x4a, 72}, /* 0xe */
+ { 0x29,0x61, 75}, /* 0xf */
+ { 0x6e,0x46, 76}, /* 0x10 */
+ { 0x2b,0x61, 78}, /* 0x11 */
+ { 0x31,0x42, 79}, /* 0x12 */
+ { 0xab,0x44, 83}, /* 0x13 */
+ { 0x46,0x25, 84}, /* 0x14 */
+ { 0x78,0x29, 86}, /* 0x15 */
+ { 0x62,0x44, 94}, /* 0x16 */
+ { 0x2b,0x41,104}, /* 0x17 */
+ { 0x3a,0x23,105}, /* 0x18 */
+ { 0x70,0x44,108}, /* 0x19 */
+ { 0x3c,0x23,109}, /* 0x1a */
+ { 0x5e,0x43,113}, /* 0x1b */
+ { 0xbc,0x44,116}, /* 0x1c */
+ { 0xe0,0x46,132}, /* 0x1d */
+ { 0x54,0x42,135}, /* 0x1e */
+ { 0xea,0x2a,139}, /* 0x1f */
+ { 0x41,0x22,157}, /* 0x20 */
+ { 0x70,0x24,162}, /* 0x21 */
+ { 0x30,0x21,175}, /* 0x22 */
+ { 0x4e,0x22,189}, /* 0x23 */
+ { 0xde,0x26,194}, /* 0x24 */
+ { 0x62,0x06,202}, /* 0x25 */
+ { 0x3f,0x03,229}, /* 0x26 */
+ { 0xb8,0x06,234}, /* 0x27 */
+ { 0x34,0x02,253}, /* 0x28 */
+ { 0x58,0x04,255}, /* 0x29 */
+ { 0x24,0x01,265}, /* 0x2a */
+ { 0x9b,0x02,267}, /* 0x2b */
+ { 0x70,0x05,270}, /* 0x2c */
+ { 0x25,0x01,272}, /* 0x2d */
+ { 0x9c,0x02,277}, /* 0x2e */
+ { 0x27,0x01,286}, /* 0x2f */
+ { 0x3c,0x02,291}, /* 0x30 */
+ { 0xef,0x0a,292}, /* 0x31 */
+ { 0xf6,0x0a,310}, /* 0x32 */
+ { 0x95,0x01,315}, /* 0x33 */
+ { 0xf0,0x09,324}, /* 0x34 */
+ { 0xfe,0x0a,331}, /* 0x35 */
+ { 0xf3,0x09,332}, /* 0x36 */
+ { 0xea,0x08,340}, /* 0x37 */
+ { 0xe8,0x07,376}, /* 0x38 */
+ { 0xde,0x06,389}, /* 0x39 */
+ { 0x52,0x2a, 54}, /* 0x3a */
+ { 0x52,0x6a, 27}, /* 0x3b */
+ { 0x62,0x24, 70}, /* 0x3c */
+ { 0x62,0x64, 70}, /* 0x3d */
+ { 0xa8,0x4c, 30}, /* 0x3e */
+ { 0x20,0x26, 33}, /* 0x3f */
+ { 0x31,0xc2, 39}, /* 0x40 */
+ { 0x60,0x36, 30}, /* 0x41 */
+ { 0x40,0x4A, 28}, /* 0x42 */
+ { 0x9F,0x46, 44}, /* 0x43 */
+ { 0x97,0x2C, 26}, /* 0x44 */
+ { 0x44,0xE4, 25}, /* 0x45 */
+ { 0x7E,0x32, 47}, /* 0x46 */
+ { 0x08,0x24, 31}, /* 0x47 */
+ { 0x97,0x2c, 26}, /* 0x48 */
+ { 0xCE,0x3c, 39}, /* 0x49 */
+ { 0x52,0x4A, 36}, /* 0x4a */
+ { 0x2C,0x61, 95}, /* 0x4b */
+ { 0x78,0x27,108}, /* 0x4c */
+ { 0x66,0x43,123},  /* 0x4d */
+ { 0x2c,0x61, 80},  /* 0x4e */
+ { 0x3b,0x61,108}  /* 0x4f */
+};
+
+XGI_VBVCLKDataStruct XGI330_VBVCLKData[]=
+{
+ { 0x1b,0xe1, 25}, /* 0x0 */
+ { 0x4e,0xe4, 28}, /* 0x1 */
+ { 0x57,0xe4, 31}, /* 0x2 */
+ { 0xc3,0xc8, 36}, /* 0x3 */
+ { 0x42,0x47, 40}, /* 0x4 */
+ { 0xfe,0xcd, 43}, /* 0x5 */
+ { 0x5d,0xc4, 44}, /* 0x6 */
+ { 0x52,0x47, 49}, /* 0x7 */
+ { 0x53,0x47, 50}, /* 0x8 */
+ { 0x74,0x67, 52}, /* 0x9 */
+ { 0x6d,0x66, 56}, /* 0xa */
+ { 0x5a,0x64, 65}, /* 0xb */
+ { 0x46,0x44, 67}, /* 0xc */
+ { 0xb1,0x46, 68}, /* 0xd */
+ { 0xd3,0x4a, 72}, /* 0xe */
+ { 0x29,0x61, 75}, /* 0xf */
+ { 0x6d,0x46, 75}, /* 0x10 */
+ { 0x41,0x43, 78}, /* 0x11 */
+ { 0x31,0x42, 79}, /* 0x12 */
+ { 0xab,0x44, 83}, /* 0x13 */
+ { 0x46,0x25, 84}, /* 0x14 */
+ { 0x78,0x29, 86}, /* 0x15 */
+ { 0x62,0x44, 94}, /* 0x16 */
+ { 0x2b,0x22,104}, /* 0x17 */
+ { 0x49,0x24,105}, /* 0x18 */
+ { 0xf8,0x2f,108}, /* 0x19 */
+ { 0x3c,0x23,109}, /* 0x1a */
+ { 0x5e,0x43,113}, /* 0x1b */
+ { 0xbc,0x44,116}, /* 0x1c */
+ { 0xe0,0x46,132}, /* 0x1d */
+ { 0xd4,0x28,135}, /* 0x1e */
+ { 0xea,0x2a,139}, /* 0x1f */
+ { 0x41,0x22,157}, /* 0x20 */
+ { 0x70,0x24,162}, /* 0x21 */
+ { 0x30,0x21,175}, /* 0x22 */
+ { 0x4e,0x22,189}, /* 0x23 */
+ { 0xde,0x26,194}, /* 0x24 */
+ { 0x70,0x07,202}, /* 0x25 */
+ { 0x3f,0x03,229}, /* 0x26 */
+ { 0xb8,0x06,234}, /* 0x27 */
+ { 0x34,0x02,253}, /* 0x28 */
+ { 0x58,0x04,255}, /* 0x29 */
+ { 0x24,0x01,265}, /* 0x2a */
+ { 0x9b,0x02,267}, /* 0x2b */
+ { 0x70,0x05,270}, /* 0x2c */
+ { 0x25,0x01,272}, /* 0x2d */
+ { 0x9c,0x02,277}, /* 0x2e */
+ { 0x27,0x01,286}, /* 0x2f */
+ { 0x3c,0x02,291}, /* 0x30 */
+ { 0xef,0x0a,292}, /* 0x31 */
+ { 0xf6,0x0a,310}, /* 0x32 */
+ { 0x95,0x01,315}, /* 0x33 */
+ { 0xf0,0x09,324}, /* 0x34 */
+ { 0xfe,0x0a,331}, /* 0x35 */
+ { 0xf3,0x09,332}, /* 0x36 */
+ { 0xea,0x08,340}, /* 0x37 */
+ { 0xe8,0x07,376}, /* 0x38 */
+ { 0xde,0x06,389}, /* 0x39 */
+ { 0x52,0x2a, 54}, /* 0x3a */
+ { 0x52,0x6a, 27}, /* 0x3b */
+ { 0x62,0x24, 70}, /* 0x3c */
+ { 0x62,0x64, 70}, /* 0x3d */
+ { 0xa8,0x4c, 30}, /* 0x3e */
+ { 0x20,0x26, 33}, /* 0x3f */
+ { 0x31,0xc2, 39}, /* 0x40 */
+ { 0x2e,0x48, 25}, /* 0x41 */
+ { 0x24,0x46, 25}, /* 0x42 */
+ { 0x26,0x64, 28}, /* 0x43 */
+ { 0x37,0x64, 40}, /* 0x44 */
+ { 0xa1,0x42,108}, /* 0x45 */
+ { 0x37,0x61,100}, /* 0x46 */
+ { 0x78,0x27,108}, /* 0x47 */
+ { 0x5e,0x64,68},  /* 0x48 chiawen for fuj1280x768*/
+ { 0x70,0x44,108}, /* 0x49 chiawen for 1400x1050*/
+};
+
+UCHAR XGI330_ScreenOffset[]={ 0x14,0x19,0x20,0x28,0x32,0x40,0x50,0x64,0x78,0x80,0x2d,0x35,0x57,0x48 };
+
+XGI_StResInfoStruct XGI330_StResInfo[]=
+{
+ { 640,400},
+ { 640,350},
+ { 720,400},
+ { 720,350},
+ { 640,480}
+};
+
+XGI_ModeResInfoStruct XGI330_ModeResInfo[]=
+{
+ {  320, 200, 8, 8},
+ {  320, 240, 8, 8},
+ {  320, 400, 8, 8},
+ {  400, 300, 8, 8},
+ {  512, 384, 8, 8},
+ {  640, 400, 8,16},
+ {  640, 480, 8,16},
+ {  800, 600, 8,16},
+ { 1024, 768, 8,16},
+ { 1280,1024, 8,16},
+ { 1600,1200, 8,16},
+ { 1920,1440, 8,16},
+ { 2048,1536, 8,16},
+ {  720, 480, 8,16},
+ {  720, 576, 8,16},
+ { 1280, 960, 8,16},
+ {  800, 480, 8,16},
+ { 1024, 576, 8,16},
+ { 1280, 720, 8,16},
+ {  856, 480, 8,16},
+ { 1280, 768, 8,16},
+ { 1400,1050, 8,16},
+ { 1152, 864, 8,16}
+};
+
+UCHAR XGI330_OutputSelect =0x40;
+UCHAR XGI330_SoftSetting = 0x30;
+UCHAR XGI330_SR07=0x18;
+UCHAR XGI330New_SR15[8][8]={
+{0x0,0x4,0x60,0x60},
+{0xf,0xf,0xf,0xf},
+{0xba,0xba,0xba,0xba},
+{0xa9,0xa9,0xac,0xac},
+{0xa0,0xa0,0xa0,0xa8},
+{0x0,0x0,0x2,0x2},
+{0x30,0x30,0x40,0x40},
+{0x0,0xa5,0xfb,0xf6}
+};
+
+UCHAR XGI330New_CR40[5][8]={
+{0x77,0x77,0x44,0x44},
+{0x77,0x77,0x44,0x44},
+{0x0,0x0,0x0,0x0},
+{0x5b,0x5b,0xab,0xab},
+{0x0,0x0,0xf0,0xf8}
+};
+
+UCHAR XGI330_CR49[]={0xaa,0x88};
+UCHAR XGI330_SR1F=0x0;
+UCHAR XGI330_SR21=0xa3;
+UCHAR XGI330_650_SR21=0xa7;
+UCHAR XGI330_SR22=0xfb;
+UCHAR XGI330_SR23=0xf6;
+UCHAR XGI330_SR24=0xd;
+
+UCHAR XGI660_SR21=0xa3;/* 2003.0312 */
+UCHAR XGI660_SR22=0xf3;/* 2003.0312 */
+
+UCHAR XGI330_LVDS_SR32=0x00;   /* ynlai for 650 LVDS */
+UCHAR XGI330_LVDS_SR33=0x00;   /* chiawen for 650 LVDS */
+UCHAR XGI330_650_SR31=0x40;
+UCHAR XGI330_650_SR33=0x04;
+UCHAR XGI330_CRT2Data_1_2 = 0x0;
+UCHAR XGI330_CRT2Data_4_D = 0x0;
+UCHAR XGI330_CRT2Data_4_E = 0x0;
+UCHAR XGI330_CRT2Data_4_10 = 0x80;
+USHORT XGI330_RGBSenseData = 0xd1;
+USHORT XGI330_VideoSenseData = 0xb9;
+USHORT XGI330_YCSenseData = 0xb3;
+USHORT XGI330_RGBSenseData2 = 0x0190;     /*301b*/
+USHORT XGI330_VideoSenseData2 = 0x0110;
+USHORT XGI330_YCSenseData2 = 0x016B;
+UCHAR XGI330_NTSCPhase[] = {0x21,0xed,0x8a,0x8};
+UCHAR XGI330_PALPhase[] = {0x2a,0x5,0xd3,0x0};
+UCHAR XGI330_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6};/*301b*/
+UCHAR XGI330_PALPhase2[] = {0x2a,0x09,0x86,0xe9};
+UCHAR XGI330_PALMPhase[] = {0x21,0xE4,0x2E,0x9B};   /*palmn*/
+UCHAR XGI330_PALNPhase[] = {0x21,0xF4,0x3E,0xBA};
+UCHAR XG40_I2CDefinition = 0x00 ;
+UCHAR XG20_CR97 = 0x10 ;
+
+UCHAR XG21_DVOSetting = 0x00 ;
+UCHAR XG21_CR2E = 0x00 ;
+UCHAR XG21_CR2F = 0x00 ;
+UCHAR XG21_CR46 = 0x00 ;
+UCHAR XG21_CR47 = 0x00 ;
+
+UCHAR XG27_CR97 = 0xC1 ;
+UCHAR XG27_SR36 = 0x30 ;
+UCHAR XG27_CR8F = 0x0C ;
+UCHAR XG27_CRD0[] = {0,0,0,0,0,0,0,0x82,0x00,0x66,0x01,0x00} ;
+UCHAR XG27_CRDE[] = {0,0} ;
+UCHAR XG27_SR40 = 0x04 ;
+UCHAR XG27_SR41 = 0x00 ;
+
+UCHAR XGI330_CHTVVCLKUNTSC[]={0x00 };
+
+UCHAR XGI330_CHTVVCLKONTSC[]={0x00 };
+
+UCHAR XGI330_CHTVVCLKUPAL[]={0x00 };
+
+UCHAR XGI330_CHTVVCLKOPAL[]={0x00 };
+
+UCHAR XGI7007_CHTVVCLKUNTSC[]={CH7007TVVCLK30_2,
+                               CH7007TVVCLK30_2,
+                               CH7007TVVCLK30_2,
+                               CH7007TVVCLK30_2,
+                               CH7007TVVCLK28_1,
+                               CH7007TVVCLK47_8
+                              };
+
+UCHAR XGI7007_CHTVVCLKONTSC[]={CH7007TVVCLK26_4,
+                               CH7007TVVCLK26_4,
+                               CH7007TVVCLK26_4,
+                               CH7007TVVCLK26_4,
+                               CH7007TVVCLK24_6,
+                               CH7007TVVCLK43_6
+                              };
+
+UCHAR XGI7007_CHTVVCLKUPAL[]={CH7007TVVCLK31_5,
+                              CH7007TVVCLK31_5,
+                              CH7007TVVCLK31_5,
+                              CH7007TVVCLK31_5,
+                              CH7007TVVCLK26_2,
+                              CH7007TVVCLK39
+                             };
+
+UCHAR XGI7007_CHTVVCLKOPAL[]={CH7007TVVCLK31_5,
+                              CH7007TVVCLK31_5,
+                              CH7007TVVCLK31_5,
+                              CH7007TVVCLK31_5,
+                              CH7007TVVCLK26_2,
+                              CH7007TVVCLK36
+                             };
+
+XGI330_VCLKDataStruct XGI_CH7007VCLKData[]=
+{
+ { 0x60,0x36,30},  /* 0 30.2 MHZ */
+ { 0x40,0x4A,28},  /* 1 28.19 MHZ */
+ { 0x9F,0x46,44},  /* 2 43.6 MHZ */
+ { 0x97,0x2C,26},  /* 3 26.4 MHZ */
+ { 0x44,0xE4,25},  /* 4 24.6 MHZ */
+ { 0x7E,0x32,47},  /* 5 47.832 MHZ */
+ { 0x8A,0x24,31},  /* 6 31.5 MHZ */
+ { 0x97,0x2C,26},  /* 7 26.2 MHZ */
+ { 0xCE,0x3C,39},  /* 8 39 MHZ   */
+ { 0x52,0x4A,36},  /* 9 36 MHZ   */
+ { 0xFF,0x00,0 }   /* End mark      */
+};
+
+XGI330_VCLKDataStruct XGI_VCLKData[]=
+{
+                       /* SR2B,SR2C,SR2D */
+               {      0x1B,0xE1,25               },/* 00 (25.175MHz) */
+
+               {      0x4E,0xE4,28               },/* 01 (28.322MHz) */
+
+                {      0x57,0xE4,31               },/* 02 (31.500MHz) */
+
+                {      0xC3,0xC8,36               },/* 03 (36.000MHz) */
+
+                {      0x42,0xE2,40               },/* 04 (40.000MHz) */
+
+                {      0xFE,0xCD,43               },/* 05 (43.163MHz) */
+
+                {      0x5D,0xC4,44               },/* 06 (44.900MHz) */
+
+                {      0x52,0xE2,49               },/* 07 (49.500MHz) */
+
+                {      0x53,0xE2,50               },/* 08 (50.000MHz) */
+
+                {      0x74,0x67,52               },/* 09 (52.406MHz) */
+
+                {      0x6D,0x66,56               },/* 0A (56.250MHz) */
+
+                {      0x6C,0xC3,65               },/* 0B (65.000MHz) */
+
+                {      0x46,0x44,67               },/* 0C (67.765MHz) */
+
+                {      0xB1,0x46,68               },/* 0D (68.179MHz) */
+
+                {      0xD3,0x4A,72               },/* 0E (72.852MHz) */
+
+                {      0x29,0x61,75              },/* 0F (75.000MHz) */
+
+                {      0x6E,0x46,76               },/* 10 (75.800MHz) */
+
+                {      0x2B,0x61,78               },/* 11 (78.750MHz) */
+
+                {      0x31,0x42,79               },/* 12 (79.411MHz) */
+
+                {      0xAB,0x44,83               },/* 13 (83.950MHz) */
+
+                {      0x46,0x25,84               },/* 14 (84.800MHz) */
+
+                {      0x78,0x29,86               },/* 15 (86.600MHz) */
+
+                {      0x62,0x44,94               },/* 16 (94.500MHz) */
+
+                {      0x2B,0x41,104               },/* 17 (104.998MHz) */
+
+                {      0x3A,0x23,105               },/* 18 (105.882MHz) */
+
+                {      0x70,0x44,108               },/* 19 (107.862MHz) */
+
+                {      0x3C,0x23,109               },/* 1A (109.175MHz) */
+
+                {      0x5E,0x43,113              },/* 1B (113.309MHz) */
+
+                {      0xBC,0x44,116              },/* 1C (116.406MHz) */
+
+                {      0xE0,0x46,132              },/* 1D (132.258MHz) */
+
+                {      0x54,0x42,135               },/* 1E (135.500MHz) */
+
+                {      0x9C,0x22,139               },/* 1F (139.275MHz) */
+
+                {      0x41,0x22,157               },/* 20 (157.500MHz) */
+
+                {      0x70,0x24,162               },/* 21 (161.793MHz) */
+
+                {      0x30,0x21,175               },/* 22 (175.000MHz) */
+
+                {      0x4E,0x22,189              },/* 23 (188.520MHz) */
+
+                {      0xDE,0x26,194              },/* 24 (194.400MHz) */
+
+                {      0x62,0x06,202               },/* 25 (202.500MHz) */
+
+                {      0x3F,0x03,229               },/* 26 (229.500MHz) */
+
+                {      0xB8,0x06,234               },/* 27 (233.178MHz) */
+
+                {      0x34,0x02,253               },/* 28 (252.699MHz) */
+
+                {      0x58,0x04,255               },/* 29 (254.817MHz) */
+
+                {      0x24,0x01,265              },/* 2A (265.728MHz) */
+
+                {      0x9B,0x02,267               },/* 2B (266.952MHz) */
+
+                {      0x70,0x05,270               },/* 2C (269.65567MHz) */
+
+                {      0x25,0x01,272               },/* 2D (272.04199MHz) */
+
+                {      0x9C,0x02,277               },/* 2E (277.015MHz) */
+
+                {      0x27,0x01,286               },/* 2F (286.359985MHz) */
+
+                {      0xB3,0x04,291               },/* 30 (291.13266MHz) */
+
+                {      0xBC,0x05,292               },/* 31 (291.766MHz) */
+
+                {      0xF6,0x0A,310               },/* 32 (309.789459MHz) */
+
+                {      0x95,0x01,315               },/* 33 (315.195MHz) */
+
+                {      0xF0,0x09,324               },/* 34 (323.586792MHz) */
+
+                {      0xFE,0x0A,331               },/* 35 (330.615631MHz) */
+
+                {      0xF3,0x09,332              },/* 36 (332.177612MHz) */
+
+                {      0x5E,0x03,340              },/* 37 (340.477MHz) */
+
+                {      0xE8,0x07,376              },/* 38 (375.847504MHz) */
+
+                {      0xDE, 0x06,389             },/* 39 (388.631439MHz) */
+
+                {      0x52,0x2A,54               },/* 3A (54.000MHz) */
+
+                {      0x52,0x6A,27              },/* 3B (27.000MHz) */
+
+                {      0x62,0x24,70               },/* 3C (70.874991MHz) */
+
+                {      0x62,0x64,70               },/* 3D (70.1048912MHz) */
+
+                {      0xA8,0x4C,30               },/* 3E (30.1048912MHz) */
+
+                {      0x20,0x26,33               },/* 3F (33.7499957MHz) */
+
+                {      0x31,0xc2,39               },/* 40 (39.77MHz) */
+
+                {      0x11,0x21,30               },/* 41 (30MHz) }// NTSC 1024X768 */
+
+                {      0x2E,0x48,25               },/* 42 (25.175MHz) }// ScaleLCD */
+
+                {      0x24,0x46,25               },/* 43 (25.175MHz) */
+
+                {      0x26,0x64,28               },/* 44 (28.322MHz) */
+
+                {      0x37,0x64,40               },/* 45 (40.000MHz) */
+
+                {      0xA1,0x42,108               },/* 46 (95.000MHz) }// QVGA */
+
+                {      0x37,0x61,100               },/* 47 (100.00MHz) */
+
+                {      0x78,0x27,108               },/* 48 (108.200MHz) */
+
+                {      0xBF,0xC8,35               },/* 49 (35.2MHz) */
+
+                {      0x66,0x43,123               },/* 4A (122.61Mhz) */
+
+                {      0x2C,0x61,80               },/* 4B (80.350Mhz) */
+
+                {      0x3B,0x61,108               },/* 4C (107.385Mhz) */
+
+
+/*                {      0x60,0x36,30               },// 4D (30.200MHz)   }// No use
+
+                {      0x60,0x36,30               },// 4E (30.200MHz)   }// No use
+
+                {      0x60,0x36,30               },// 4F (30.200MHz)   }// No use
+
+                {      0x60,0x36,30               },// 50 (30.200MHz)   }// CHTV
+
+                {      0x40,0x4A,28               },// 51 (28.190MHz)
+
+                {      0x9F,0x46,44               },// 52 (43.600MHz)
+
+                {      0x97,0x2C,26               },// 53 (26.400MHz)
+
+                {      0x44,0xE4,25               },// 54 (24.600MHz)
+
+                {      0x7E,0x32,47               },// 55 (47.832MHz)
+
+                {      0x8A,0x24,31               },// 56 (31.500MHz)
+
+                {      0x97,0x2C,26               },// 57 (26.200MHz)
+
+                {      0xCE,0x3C,39               },// 58 (39.000MHz)
+
+                {      0x52,0x4A,36               },// 59 (36.000MHz)
+
+*/
+               {      0x69,0x61,191              }, /* 4D (190.96MHz ) */
+               {      0x4F,0x22,192              }, /* 4E (192.069MHz) */
+               {      0x28,0x26,322              }, /* 4F (322.273MHz) */
+               {      0x5C,0x6B,27               }, /* 50 (27.74HMz) */
+               {      0x57,0x24,126              }, /* 51 (125.999MHz) */
+               {      0x5C,0x42,148              }, /* 52 (148.5MHz) */
+               {      0x42,0x61,120              }, /* 53 (120.839MHz) */
+               {      0x62,0x61,178              }, /* 54 (178.992MHz) */
+               {      0x59,0x22,217              }, /* 55 (217.325MHz) */
+               {      0x29,0x01,300              }, /* 56 (299.505Mhz) */
+               {      0x52,0x63,74               }, /* 57 (74.25MHz) */
+
+
+                {      0xFF,0x00,0                }/* End mark */
+ }  ;
+
+XGI330_VCLKDataStruct XGI_VBVCLKData[]=
+{
+                {      0x1B,0xE1,25               },/* 00 (25.175MHz) */
+
+                {      0x4E,0xE4,28               },/* 01 (28.322MHz) */
+
+                {      0x57,0xE4,31               },/* 02 (31.500MHz) */
+
+                {      0xC3,0xC8,36               },/* 03 (36.000MHz) */
+
+                {      0x42,0x47,40               },/* 04 (40.000MHz) */
+
+                {      0xFE,0xCD,43               },/* 05 (43.163MHz) */
+
+                {      0x5D,0xC4,44               },/* 06 (44.900MHz) */
+
+                {      0x52,0x47,49               },/* 07 (49.500MHz) */
+
+                {      0x53,0x47,50               },/* 08 (50.000MHz) */
+
+                {      0x74,0x67,52               },/* 09 (52.406MHz) */
+
+                {      0x6D,0x66,56               },/* 0A (56.250MHz) */
+
+                {      0x35,0x62,65               },/* 0B (65.000MHz) */
+
+                {      0x46,0x44,67               },/* 0C (67.765MHz) */
+
+                {      0xB1,0x46,68               },/* 0D (68.179MHz) */
+
+                {      0xD3,0x4A,72               },/* 0E (72.852MHz) */
+
+                {      0x29,0x61,75               },/* 0F (75.000MHz) */
+
+                {      0x6D,0x46,75               },/* 10 (75.800MHz) */
+
+                {      0x41,0x43,78               },/* 11 (78.750MHz) */
+
+                {      0x31,0x42,79               },/* 12 (79.411MHz) */
+
+                {      0xAB,0x44,83               },/* 13 (83.950MHz) */
+
+                {      0x46,0x25,84               },/* 14 (84.800MHz) */
+
+                {      0x78,0x29,86               },/* 15 (86.600MHz) */
+
+                {      0x62,0x44,94               },/* 16 (94.500MHz) */
+
+                {      0x2B,0x22,104               },/* 17 (104.998MHz) */
+
+                {      0x49,0x24,105               },/* 18 (105.882MHz) */
+
+                {      0xF8,0x2F,108               },/* 19 (108.279MHz) */
+
+                {      0x3C,0x23,109               },/* 1A (109.175MHz) */
+
+                {      0x5E,0x43,113               },/* 1B (113.309MHz) */
+
+                {      0xBC,0x44,116               },/* 1C (116.406MHz) */
+
+                {      0xE0,0x46,132               },/* 1D (132.258MHz) */
+
+                {      0xD4,0x28,135               },/* 1E (135.220MHz) */
+
+                {      0xEA,0x2A,139               },/* 1F (139.275MHz) */
+
+                {      0x41,0x22,157               },/* 20 (157.500MHz) */
+
+                {      0x70,0x24,162               },/* 21 (161.793MHz) */
+
+                {      0x30,0x21,175               },/* 22 (175.000MHz) */
+
+                {      0x4E,0x22,189               },/* 23 (188.520MHz) */
+
+                {      0xDE,0x26,194               },/* 24 (194.400MHz) */
+
+                {      0x70,0x07,202               },/* 25 (202.500MHz) */
+
+                {      0x3F,0x03,229               },/* 26 (229.500MHz) */
+
+                {      0xB8,0x06,234               },/* 27 (233.178MHz) */
+
+                {      0x34,0x02,253               },/* 28 (252.699997 MHz) */
+
+                {      0x58,0x04,255               },/* 29 (254.817MHz) */
+
+                {      0x24,0x01,265               },/* 2A (265.728MHz) */
+
+                {      0x9B,0x02,267               },/* 2B (266.952MHz) */
+
+                {      0x70,0x05,270               },/* 2C (269.65567 MHz) */
+
+                {      0x25,0x01,272               },/* 2D (272.041992 MHz) */
+
+                {      0x9C,0x02,277               },/* 2E (277.015MHz) */
+
+                {      0x27,0x01,286               },/* 2F (286.359985 MHz) */
+
+                {      0x3C,0x02,291               },/* 30 (291.132660 MHz) */
+
+                {      0xEF,0x0A,292               },/* 31 (291.766MHz) */
+
+                {      0xF6,0x0A,310               },/* 32 (309.789459 MHz) */
+
+                {      0x95,0x01,315               },/* 33 (315.195MHz) */
+
+                {      0xF0,0x09,324               },/* 34 (323.586792 MHz) */
+
+                {      0xFE,0x0A,331               },/* 35 (330.615631 MHz) */
+
+                {      0xF3,0x09,332               },/* 36 (332.177612 MHz) */
+
+                {      0xEA,0x08,340               },/* 37 (340.477MHz) */
+
+                {      0xE8,0x07,376               },/* 38 (375.847504 MHz) */
+
+                {      0xDE,0x06,389               },/* 39 (388.631439 MHz) */
+
+                {      0x52,0x2A,54                },/* 3A (54.000MHz) */
+
+                {      0x52,0x6A,27                },/* 3B (27.000MHz) */
+
+
+                {      0x62,0x24,70                },/* 3C (70.874991MHz) */
+
+
+                {      0x62,0x64,70                },/* 3D (70.1048912MHz) */
+
+                {      0xA8,0x4C,30                },/* 3E (30.1048912MHz) */
+
+                {      0x20,0x26,33                },/* 3F (33.7499957MHz) */
+
+                {      0x31,0xc2,39                },/* 40 (39.77MHz) */
+
+                {      0x11,0x21,30                },/* 41 (30MHz) }// NTSC 1024X768 */
+
+                {      0x2E,0x48,25                },/* 42 (25.175MHz) }// ScaleLCD */
+
+                {      0x24,0x46,25                },/* 43 (25.175MHz) */
+
+                {      0x26,0x64,28                },/* 44 (28.322MHz) */
+
+                {      0x37,0x64,40                },/* 45 (40.000MHz) */
+
+                {      0xA1,0x42,108               },/* 46 (95.000MHz) }// QVGA */
+
+                {      0x37,0x61,100               },/* 47 (100.00MHz) */
+
+                {      0x78,0x27,108               },/* 48 (108.200MHz) */
+
+                {      0xBF,0xC8,35                },/* 49 (35.2MHz) */
+
+                {      0x66,0x43,123               },/* 4A (122.61Mhz) */
+
+                {      0x2C,0x61,80                },/* 4B (80.350Mhz) */
+
+                {      0x3B,0x61,108               },/* 4C (107.385Mhz) */
+
+/*
+                {      0x60,0x36,30               },// 4D (30.200MHz)   }// No use
+
+                {      0x60,0x36,30               },// 4E (30.200MHz)   }// No use
+
+                {      0x60,0x36,30               },// 4F (30.200MHz)   }// No use
+
+                {      0x60,0x36,30               },// 50 (30.200MHz)   }// CHTV
+
+                {      0x40,0x4A,28               },// 51 (28.190MHz)
+
+                {      0x9F,0x46,44               },// 52 (43.600MHz)
+
+                {      0x97,0x2C,26               },// 53 (26.400MHz)
+
+                {      0x44,0xE4,25               },// 54 (24.600MHz)
+
+                {      0x7E,0x32,47               },// 55 (47.832MHz)
+
+                {      0x8A,0x24,31               },// 56 (31.500MHz)
+
+                {      0x97,0x2C,26               },// 57 (26.200MHz)
+
+                {      0xCE,0x3C,39               },// 58 (39.000MHz)
+
+                {      0x52,0x4A,36               },// 59 (36.000MHz)
+*/
+               {      0x69,0x61,191              }, /* 4D (190.96MHz ) */
+               {      0x4F,0x22,192              }, /* 4E (192.069MHz) */
+               {      0x28,0x26,322              }, /* 4F (322.273MHz) */
+               {      0x5C,0x6B,27               }, /* 50 (27.74HMz) */
+               {      0x57,0x24,126              }, /* 51 (125.999MHz) */
+               {      0x5C,0x42,148              }, /* 52 (148.5MHz) */
+               {      0x42,0x61,120              }, /* 53 (120.839MHz) */
+               {      0x62,0x61,178              }, /* 54 (178.992MHz) */
+               {      0x59,0x22,217              }, /* 55 (217.325MHz) */
+               {      0x29,0x01,300              }, /* 56 (299.505Mhz) */
+               {      0x52,0x63,74               }, /* 57 (74.25MHz) */
+
+
+                {      0xFF,0x00,0                }      /* End mark */
+};
+
+UCHAR XGI660_TVDelayList[]=
+{
+          0x44,            /* ; 0 ExtNTSCDelay */
+          0x44,            /* ; 1 StNTSCDelay */
+          0x44,            /* ; 2 ExtPALDelay */
+          0x44,            /* ; 3 StPALDelay */
+          0x44,            /* ; 4 ExtHiTVDelay(1080i) */
+          0x44,            /* ; 5 StHiTVDelay(1080i) */
+          0x44,            /* ; 6 ExtYPbPrDelay(525i) */
+          0x44,            /* ; 7 StYPbPrDealy(525i) */
+          0x44,            /* ; 8 ExtYPbPrDelay(525p) */
+          0x44,            /* ; 9 StYPbPrDealy(525p) */
+          0x44,            /* ; A ExtYPbPrDelay(750p) */
+          0x44             /* ; B StYPbPrDealy(750p) */
+};
+
+UCHAR XGI660_TVDelayList2[]=
+{
+          0x44,           /* ; 0 ExtNTSCDelay */
+          0x44,           /* ; 1 StNTSCDelay */
+          0x44,           /* ; 2 ExtPALDelay */
+          0x44,           /* ; 3 StPALDelay */
+          0x44,           /* ; 4 ExtHiTVDelay */
+          0x44,           /* ; 5 StHiTVDelay */
+          0x44,           /* ; 6 ExtYPbPrDelay(525i) */
+          0x44,           /* ; 7 StYPbPrDealy(525i) */
+          0x44,           /* ; 8 ExtYPbPrDelay(525p) */
+          0x44,           /* ; 9 StYPbPrDealy(525p) */
+          0x44,           /* ; A ExtYPbPrDelay(750p) */
+          0x44            /* ; B StYPbPrDealy(750p) */
+};
+
+UCHAR XGI301TVDelayList[]=
+{
+       0x22,            /* ; 0 ExtNTSCDelay */
+       0x22,            /* ; 1 StNTSCDelay */
+       0x22,            /* ; 2 ExtPALDelay */
+       0x22,            /* ; 3 StPALDelay */
+       0x88,            /* ; 4 ExtHiTVDelay(1080i) */
+       0xBB,            /* ; 5 StHiTVDelay(1080i) */
+       0x22,            /* ; 6 ExtYPbPrDelay(525i) */
+       0x22,            /* ; 7 StYPbPrDealy(525i) */
+       0x22,            /* ; 8 ExtYPbPrDelay(525p) */
+       0x22,            /* ; 9 StYPbPrDealy(525p) */
+       0x22,            /* ; A ExtYPbPrDelay(750p) */
+       0x22            /* B StYPbPrDealy(750p) */
+};
+
+UCHAR XGI301TVDelayList2[]=
+{
+       0x22,           /* ; 0 ExtNTSCDelay */
+       0x22,           /* ; 1 StNTSCDelay */
+       0x22,           /* ; 2 ExtPALDelay */
+       0x22,           /* ; 3 StPALDelay */
+       0x22,           /* ; 4 ExtHiTVDelay */
+       0x22,           /* ; 5 StHiTVDelay */
+       0x22,           /* ; 6 ExtYPbPrDelay(525i) */
+       0x22,           /* ; 7 StYPbPrDealy(525i) */
+       0x22,           /* ; 8 ExtYPbPrDelay(525p) */
+       0x22,           /* ; 9 StYPbPrDealy(525p) */
+       0x22,           /* ; A ExtYPbPrDelay(750p) */
+       0x22            /* ; B StYPbPrDealy(750p) */
+};
+
+
+UCHAR TVAntiFlickList[]=
+{/* NTSCAntiFlicker */
+                      0x04,           /* ; 0 Adaptive */
+                      0x00,           /* ; 1 new anti-flicker ? */
+/* PALAntiFlicker */
+                      0x04,           /* ; 0 Adaptive */
+                      0x08,           /* ; 1 new anti-flicker ? */
+/* HiTVAntiFlicker */
+                      0x04,           /* ; 0 ? */
+                      0x00            /* ; 1 new anti-flicker ? */
+};
+
+
+UCHAR TVEdgeList[]=
+{
+      0x00,            /* ; 0 NTSC No Edge enhance */
+      0x04,            /* ; 1 NTSC Adaptive Edge enhance */
+      0x00,            /* ; 0 PAL No Edge enhance */
+      0x04,            /* ; 1 PAL Adaptive Edge enhance */
+      0x00,            /* ; 0 HiTV */
+      0x00             /* ; 1 HiTV */
+};
+
+ULONG TVPhaseList[]=
+{      0x08BAED21, /* ; 0 NTSC phase */
+       0x00E3052A, /* ; 1 PAL phase */
+       0x9B2EE421, /* ; 2 PAL-M phase */
+       0xBA3EF421, /* ; 3 PAL-N phase */
+       0xA7A28B1E, /* ; 4 NTSC 1024x768 */
+       0xE00A831E, /* ; 5 PAL-M 1024x768 */
+       0x00000000, /* ; 6 reserved */
+       0x00000000, /* ; 7 reserved */
+       0xD67BF021, /* ; 8 NTSC phase */
+       0xE986092A, /* ; 9 PAL phase */
+       0xA4EFE621, /* ; A PAL-M phase */
+       0x4694F621, /* ; B PAL-N phase */
+       0x8BDE711C, /* ; C NTSC 1024x768 */
+       0xE00A831E  /* ; D PAL-M 1024x768 */
+};
+
+UCHAR NTSCYFilter1[]=
+{
+                     0x00,0xF4,0x10,0x38     ,/* 0 : 320x text mode */
+                      0x00,0xF4,0x10,0x38     ,/* 1 : 360x text mode */
+                      0xEB,0x04,0x25,0x18     ,/* 2 : 640x text mode */
+                      0xF1,0x04,0x1F,0x18     ,/* 3 : 720x text mode */
+                      0x00,0xF4,0x10,0x38     ,/* 4 : 320x gra. mode */
+                      0xEB,0x04,0x25,0x18     ,/* 5 : 640x gra. mode */
+                      0xEB,0x15,0x25,0xF6     /* 6 : 800x gra. mode */
+};
+
+UCHAR PALYFilter1[]=
+{
+                     0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
+                      0x00,0xF4,0x10,0x38     ,/* 1 : 360x text mode */
+                      0xF1,0xF7,0x1F,0x32     ,/* 2 : 640x text mode */
+                      0xF3,0x00,0x1D,0x20     ,/* 3 : 720x text mode */
+                      0x00,0xF4,0x10,0x38     ,/* 4 : 320x gra. mode */
+                      0xF1,0xF7,0x1F,0x32     ,/* 5 : 640x gra. mode */
+                      0xFC,0xFB,0x14,0x2A     /* 6 : 800x gra. mode */
+};
+
+UCHAR PALMYFilter1[]=
+{
+                     0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
+                      0x00,0xF4,0x10,0x38, /* 1 : 360x text mode */
+                      0xEB,0x04,0x10,0x18, /* 2 : 640x text mode */
+                      0xF7,0x06,0x19,0x14, /* 3 : 720x text mode */
+                      0x00,0xF4,0x10,0x38, /* 4 : 320x gra. mode */
+                      0xEB,0x04,0x25,0x18, /* 5 : 640x gra. mode */
+                      0xEB,0x15,0x25,0xF6, /* 6 : 800x gra. mode */
+                      0xFF,0xFF,0xFF,0xFF  /* End of Table */
+};
+
+UCHAR PALNYFilter1[]=
+{
+                     0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
+                      0x00,0xF4,0x10,0x38, /* 1 : 360x text mode */
+                      0xEB,0x04,0x10,0x18, /* 2 : 640x text mode */
+                      0xF7,0x06,0x19,0x14, /* 3 : 720x text mode */
+                      0x00,0xF4,0x10,0x38, /* 4 : 320x gra. mode */
+                      0xEB,0x04,0x25,0x18, /* 5 : 640x gra. mode */
+                      0xEB,0x15,0x25,0xF6, /* 6 : 800x gra. mode */
+                      0xFF,0xFF,0xFF,0xFF  /* End of Table */
+};
+
+UCHAR NTSCYFilter2[]=
+{
+                     0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+                      0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
+                      0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
+                      0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
+                      0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28  /* 7 : 1024xgra. mode */
+};
+
+UCHAR PALYFilter2[]=
+{
+                     0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+                      0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
+                      0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
+                      0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
+                      0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28  /* 7 : 1024xgra. mode */
+};
+
+UCHAR PALMYFilter2[]=
+{
+                     0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+                      0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
+                      0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
+                      0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
+                      0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28  /* 7 : 1024xgra. mode */
+};
+
+UCHAR PALNYFilter2[]=
+{
+                     0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+                      0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
+                      0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
+                      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
+                      0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
+                      0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28  /* 7 : 1024xgra. mode */
+};
+
+UCHAR XGI_NTSC1024AdjTime[]=
+{
+      0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
+      0x13,0x40,0x34,0xF4,0x63,0xBB,0xCC,0x7A,
+      0x58,0xe4,0x73,0xd0,0x13
+};
+
+XGI301C_Tap4TimingStruct HiTVTap4Timing[]=
+{
+       {0,{
+       0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
+       0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */
+       0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */
+       0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */
+       0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */
+       0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */
+       0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */
+       0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E  /* ; F8-FF */
+       }
+       }
+};
+
+XGI301C_Tap4TimingStruct EnlargeTap4Timing[]=
+{
+       {0,{
+       0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
+       0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */
+       0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */
+       0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */
+       0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */
+       0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */
+       0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */
+       0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E   /* ; F8-FF */
+       }
+       }
+};
+
+XGI301C_Tap4TimingStruct NoScaleTap4Timing[]=
+{
+       {0,{
+       0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
+       0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */
+       0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */
+       0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */
+       0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */
+       0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */
+       0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */
+       0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E  /* ; F8-FF */
+       }
+       }
+};
+
+XGI301C_Tap4TimingStruct PALTap4Timing[]=
+{
+       {600,  {
+                0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E, /* ; C0-C7 */
+                0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D, /* ; C8-CF */
+                0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C, /* ; D0-D7 */
+                0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D, /* ; D8-DF */
+                0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E, /* ; E0-E7 */
+                0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E, /* ; EA-EF */
+                0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01, /* ; F0-F7 */
+                0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04  /* ; F8-FF */
+                }
+       },
+        {768,  {
+                0x08,0x12,0x08,0x7E,0x07,0x12,0x09,0x7E, /* ; C0-C7 */
+                0x06,0x12,0x0A,0x7E,0x05,0x11,0x0B,0x7F, /* ; C8-CF */
+                0x04,0x11,0x0C,0x7F,0x03,0x11,0x0C,0x00, /* ; D0-D7 */
+                0x03,0x10,0x0D,0x00,0x02,0x0F,0x0E,0x01, /* ; D8-DF */
+                0x01,0x0F,0x0F,0x01,0x01,0x0E,0x0F,0x02, /* ; E0-E7 */
+                0x00,0x0D,0x10,0x03,0x7F,0x0C,0x11,0x04, /* ; EA-EF */
+                0x7F,0x0C,0x11,0x04,0x7F,0x0B,0x11,0x05, /* ; F0-F7 */
+                0x7E,0x0A,0x12,0x06,0x7E,0x09,0x12,0x07  /* ; F8-FF */
+                }
+        },
+        {0xFFFF,
+               {
+                0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E, /* ; C0-C7 */
+                0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D, /* ; C8-CF */
+                0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D, /* ; D0-D7 */
+                0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
+                0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
+                0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F, /* ; EA-EF */
+                0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00, /* ; F0-F7 */
+                0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02  /* ; F8-FF */
+                }
+        }
+};
+
+XGI301C_Tap4TimingStruct NTSCTap4Timing[]=
+{
+       {480,   {
+               0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
+               0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */
+               0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */
+               0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
+               0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
+               0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */
+               0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */
+               0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02  /* ; F8-FF */
+               }
+        },
+        {600,  {
+               0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */
+               0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */
+               0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */
+               0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */
+               0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */
+               0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */
+               0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */
+               0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06  /* ; F8-FF */
+               }
+        },
+        {0xFFFF,
+               {
+               0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */
+               0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */
+               0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */
+               0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */
+               0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */
+               0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */
+               0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */
+               0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08  /* ; F8-FF */
+               }
+        }
+};
+
+XGI301C_Tap4TimingStruct YPbPr525pTap4Timing[]=
+{
+       {480,   {
+               0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
+               0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */
+               0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */
+               0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
+               0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
+               0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */
+               0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */
+               0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02  /* ; F8-FF */
+               }
+        },
+        {600,  {
+               0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */
+               0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */
+               0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */
+               0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */
+               0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */
+               0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */
+               0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */
+               0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06  /* ; F8-FF */
+               }
+        },
+        {0xFFFF,
+               {
+               0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */
+               0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */
+               0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */
+               0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */
+               0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */
+               0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */
+               0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */
+               0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08  /* ; F8-FF */
+               }
+        }
+};
+
+XGI301C_Tap4TimingStruct YPbPr525iTap4Timing[]=
+{
+       {480,   {
+               0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
+               0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */
+               0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */
+               0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
+               0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
+               0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */
+               0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */
+               0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02  /* ; F8-FF */
+               }
+        },
+        {600,  {
+               0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */
+               0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */
+               0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */
+               0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */
+               0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */
+               0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */
+               0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */
+               0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06  /* ; F8-FF */
+               }
+        },
+        {0xFFFF,
+               {
+               0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */
+               0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */
+               0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */
+               0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */
+               0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */
+               0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */
+               0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */
+               0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08  /* ; F8-FF */
+               }
+        }
+};
+
+XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[]=
+{        {0xFFFF,
+               {
+               0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E, /* ; C0-C7 */
+               0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D, /* ; C8-CF */
+               0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C, /* ; D0-D7 */
+               0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D, /* ; D8-DF */
+               0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E, /* ; E0-E7 */
+               0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E, /* ; EA-EF */
+               0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01, /* ; F0-F7 */
+               0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04 /* F8-FF */
+               }
+        }
+};
diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
new file mode 100644 (file)
index 0000000..87531b4
--- /dev/null
@@ -0,0 +1,263 @@
+#include "osdef.h"
+#include "vb_def.h"
+#include "vgatypes.h"
+#include "vb_struct.h"
+
+#ifdef LINUX_KERNEL
+#include "XGIfb.h"
+#include <asm/io.h>
+#include <linux/types.h>
+#endif
+
+#ifdef TC
+#include <stdio.h>
+#include <string.h>
+#include <conio.h>
+#include <dos.h>
+#endif
+
+#ifdef WIN2000
+#include <dderror.h>
+#include <devioctl.h>
+#include <miniport.h>
+#include <ntddvdeo.h>
+#include <video.h>
+
+#include "xgiv.h"
+#include "dd_i2c.h"
+#include "tools.h"
+#endif
+
+#ifdef LINUX_XF86
+#include "xf86.h"
+#include "xf86PciInfo.h"
+#include "xgi.h"
+#include "xgi_regs.h"
+#endif
+
+
+
+
+void XGINew_SetReg1( ULONG , USHORT , USHORT ) ;
+void XGINew_SetReg2( ULONG , USHORT , USHORT ) ;
+void XGINew_SetReg3( ULONG , USHORT ) ;
+void XGINew_SetReg4( ULONG , ULONG ) ;
+UCHAR XGINew_GetReg1( ULONG , USHORT) ;
+UCHAR XGINew_GetReg2( ULONG ) ;
+ULONG XGINew_GetReg3( ULONG ) ;
+void XGINew_ClearDAC( PUCHAR ) ;
+void     XGINew_SetRegANDOR(ULONG Port,USHORT Index,USHORT DataAND,USHORT DataOR);
+void     XGINew_SetRegOR(ULONG Port,USHORT Index,USHORT DataOR);
+void     XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetReg1 */
+/* Input : */
+/* Output : */
+/* Description : SR CRTC GR */
+/* --------------------------------------------------------------------- */
+void XGINew_SetReg1( ULONG port , USHORT index , USHORT data )
+{
+#ifdef LINUX_XF86
+    OutPortByte( ( PUCHAR )(ULONG)port , index ) ;
+    OutPortByte( ( PUCHAR )(ULONG)port + 1 , data ) ;
+#else
+    OutPortByte( port , index ) ;
+    OutPortByte( port + 1 , data ) ;
+#endif
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetReg2 */
+/* Input : */
+/* Output : */
+/* Description : AR( 3C0 ) */
+/* --------------------------------------------------------------------- */
+/*void XGINew_SetReg2( ULONG port , USHORT index , USHORT data )
+{
+    InPortByte( ( PUCHAR )port + 0x3da - 0x3c0 ) ;
+    OutPortByte( XGINew_P3c0 , index ) ;
+    OutPortByte( XGINew_P3c0 , data ) ;
+    OutPortByte( XGINew_P3c0 , 0x20 ) ;
+}*/
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetReg3( ULONG port , USHORT data )
+{
+    OutPortByte( port , data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetReg4 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetReg4( ULONG port , ULONG data )
+{
+    OutPortLong( port , data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_GetReg1 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGINew_GetReg1( ULONG port , USHORT index )
+{
+    UCHAR data ;
+
+#ifdef LINUX_XF86
+    OutPortByte( ( PUCHAR )(ULONG)port , index ) ;
+    data = InPortByte( ( PUCHAR )(ULONG)port + 1 ) ;
+#else
+    OutPortByte( port , index ) ;
+    data = InPortByte( port + 1 ) ;
+#endif
+
+    return( data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_GetReg2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGINew_GetReg2( ULONG port )
+{
+    UCHAR data ;
+
+    data = InPortByte( port ) ;
+
+    return( data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_GetReg3 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+ULONG XGINew_GetReg3( ULONG port )
+{
+    ULONG data ;
+
+    data = InPortLong( port ) ;
+
+    return( data ) ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetRegANDOR */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetRegANDOR( ULONG Port , USHORT Index , USHORT DataAND , USHORT DataOR )
+{
+    USHORT temp ;
+
+    temp = XGINew_GetReg1( Port , Index ) ;            /* XGINew_Part1Port index 02 */
+    temp = ( temp & ( DataAND ) ) | DataOR ;
+    XGINew_SetReg1( Port , Index , temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetRegAND */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND)
+{
+    USHORT temp ;
+
+    temp = XGINew_GetReg1( Port , Index ) ;    /* XGINew_Part1Port index 02 */
+    temp &= DataAND ;
+    XGINew_SetReg1( Port , Index , temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetRegOR */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetRegOR( ULONG Port , USHORT Index , USHORT DataOR )
+{
+    USHORT temp ;
+
+    temp = XGINew_GetReg1( Port , Index ) ;    /* XGINew_Part1Port index 02 */
+    temp |= DataOR ;
+    XGINew_SetReg1( Port , Index , temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : NewDelaySecond */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void NewDelaySeconds( int seconds )
+{
+#ifdef WIN2000
+    int j ;
+#endif
+    int i ;
+
+
+    for( i = 0 ; i < seconds ; i++ )
+    {
+#ifdef TC
+        delay( 1000 ) ;
+#endif
+
+#ifdef WIN2000
+
+        for ( j = 0 ; j < 20000 ; j++ )
+            VideoPortStallExecution( 50 ) ;
+#endif
+
+#ifdef WINCE_HEADER
+#endif
+
+#ifdef LINUX_KERNEL
+#endif
+    }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : Newdebugcode */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void Newdebugcode( UCHAR code )
+{
+//    OutPortByte ( 0x80 , code ) ;
+    /* OutPortByte ( 0x300 , code ) ; */
+    /* NewDelaySeconds( 0x3 ) ; */
+}
+
+
+
diff --git a/drivers/staging/xgifb/vb_util.h b/drivers/staging/xgifb/vb_util.h
new file mode 100644 (file)
index 0000000..91779d8
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _VBUTIL_
+#define _VBUTIL_
+extern   void     NewDelaySeconds( int );
+extern   void     Newdebugcode( UCHAR );
+extern   void     XGINew_SetReg1(ULONG, USHORT, USHORT);
+extern   void     XGINew_SetReg3(ULONG, USHORT);
+extern   UCHAR    XGINew_GetReg1(ULONG, USHORT);
+extern   UCHAR    XGINew_GetReg2(ULONG);
+extern   void     XGINew_SetReg4(ULONG, ULONG);
+extern   ULONG    XGINew_GetReg3(ULONG);
+extern   void     XGINew_SetRegOR(ULONG Port,USHORT Index,USHORT DataOR);
+extern   void     XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
+extern   void     XGINew_SetRegANDOR(ULONG Port,USHORT Index,USHORT DataAND,USHORT DataOR);
+#endif
+
diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
new file mode 100644 (file)
index 0000000..295ea86
--- /dev/null
@@ -0,0 +1,325 @@
+
+#ifndef _VGATYPES_
+#define _VGATYPES_
+
+#include "osdef.h"
+
+#ifdef LINUX_XF86
+#include "xf86Version.h"
+#include "xf86Pci.h"
+#endif
+
+#ifdef LINUX_KERNEL  /* We don't want the X driver to depend on kernel source */
+#include <linux/ioctl.h>
+#endif
+
+#ifndef FALSE
+#define FALSE   0
+#endif
+
+#ifndef TRUE
+#define TRUE    1
+#endif
+
+#ifndef NULL
+#define NULL    0
+#endif
+
+#ifndef CHAR
+typedef char CHAR;
+#endif
+
+#ifndef SHORT
+typedef short SHORT;
+#endif
+
+#ifndef LONG
+typedef long  LONG;
+#endif
+
+#ifndef UCHAR
+typedef unsigned char UCHAR;
+#endif
+
+#ifndef USHORT
+typedef unsigned short USHORT;
+#endif
+
+#ifndef ULONG
+typedef unsigned long ULONG;
+#endif
+
+#ifndef PUCHAR
+typedef UCHAR *PUCHAR;
+#endif
+
+#ifndef PUSHORT
+typedef USHORT *PUSHORT;
+#endif
+
+#ifndef PLONGU
+typedef ULONG *PULONG;
+#endif
+
+#ifndef VOID
+typedef void VOID;
+#endif
+
+#ifndef PVOID
+typedef void *PVOID;
+#endif
+
+#ifndef BOOLEAN
+typedef UCHAR BOOLEAN;
+#endif
+/*
+#ifndef bool
+typedef UCHAR bool;
+#endif
+*/
+#ifdef LINUX_KERNEL
+typedef unsigned long XGIIOADDRESS;
+#endif
+
+#ifdef LINUX_XF86
+#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0)
+typedef unsigned char IOADDRESS;
+typedef unsigned char XGIIOADDRESS;
+#else
+typedef IOADDRESS XGIIOADDRESS;
+#endif
+#endif
+
+#ifndef VBIOS_VER_MAX_LENGTH
+#define VBIOS_VER_MAX_LENGTH    4
+#endif
+
+#ifndef WIN2000
+
+#ifndef LINUX_KERNEL   /* For the linux kernel, this is defined in xgifb.h */
+#ifndef XGI_CHIP_TYPE
+typedef enum _XGI_CHIP_TYPE {
+    XGI_VGALegacy = 0,
+#ifdef LINUX_XF86
+    XGI_530,
+    XGI_OLD,
+#endif
+    XGI_300,
+    XGI_630,
+    XGI_640,
+    XGI_315H,
+    XGI_315,
+    XGI_315PRO,
+    XGI_550,
+    XGI_650,
+    XGI_650M,
+    XGI_740,
+    XGI_330,
+    XGI_661,
+    XGI_660,
+    XGI_760,
+    XG40 = 32,
+    XG41,
+    XG42,
+    XG45,
+    XG20 = 48,
+    XG21,
+    XG27,
+    MAX_XGI_CHIP
+} XGI_CHIP_TYPE;
+#endif
+#endif
+
+#ifndef XGI_VB_CHIP_TYPE
+typedef enum _XGI_VB_CHIP_TYPE {
+    VB_CHIP_Legacy = 0,
+    VB_CHIP_301,
+    VB_CHIP_301B,
+    VB_CHIP_301LV,
+    VB_CHIP_302,
+    VB_CHIP_302B,
+    VB_CHIP_302LV,
+    VB_CHIP_301C,
+    VB_CHIP_302ELV,
+    VB_CHIP_UNKNOWN, /* other video bridge or no video bridge */
+    MAX_VB_CHIP
+} XGI_VB_CHIP_TYPE;
+#endif
+
+#ifndef XGI_LCD_TYPE
+typedef enum _XGI_LCD_TYPE {
+    LCD_INVALID = 0,
+    LCD_320x480,       /* FSTN, DSTN */
+    LCD_640x480,
+    LCD_640x480_2,     /* FSTN, DSTN */
+    LCD_640x480_3,     /* FSTN, DSTN */
+    LCD_800x600,
+    LCD_848x480,
+    LCD_1024x600,
+    LCD_1024x768,
+    LCD_1152x768,
+    LCD_1152x864,
+    LCD_1280x720,
+    LCD_1280x768,
+    LCD_1280x800,
+    LCD_1280x960,
+    LCD_1280x1024,
+    LCD_1400x1050,
+    LCD_1600x1200,
+    LCD_1680x1050,
+    LCD_1920x1440,
+    LCD_2048x1536,
+    LCD_CUSTOM,
+    LCD_UNKNOWN
+} XGI_LCD_TYPE;
+#endif
+
+#endif   /* not WIN2000 */
+
+#ifndef PXGI_DSReg
+typedef struct _XGI_DSReg
+{
+  UCHAR  jIdx;
+  UCHAR  jVal;
+} XGI_DSReg, *PXGI_DSReg;
+#endif
+
+#ifndef XGI_HW_DEVICE_INFO
+
+typedef struct _XGI_HW_DEVICE_INFO  XGI_HW_DEVICE_INFO, *PXGI_HW_DEVICE_INFO;
+
+typedef BOOLEAN (*PXGI_QUERYSPACE)   (PXGI_HW_DEVICE_INFO, ULONG, ULONG, ULONG *);
+
+struct _XGI_HW_DEVICE_INFO
+{
+    ULONG  ulExternalChip;       /* NO VB or other video bridge*/
+                                 /* if ujVBChipID = VB_CHIP_UNKNOWN, */
+#ifdef LINUX_XF86
+    PCITAG PciTag;              /* PCI Tag */
+#endif
+
+    PUCHAR  pjVirtualRomBase;    /* ROM image */
+
+    BOOLEAN UseROM;             /* Use the ROM image if provided */
+
+    PVOID   pDevice;
+
+    PUCHAR  pjVideoMemoryAddress;/* base virtual memory address */
+                                 /* of Linear VGA memory */
+
+    ULONG  ulVideoMemorySize;    /* size, in bytes, of the memory on the board */
+
+    PUCHAR pjIOAddress;          /* base I/O address of VGA ports (0x3B0) */
+
+    PUCHAR pjCustomizedROMImage;
+
+    PUCHAR pj2ndVideoMemoryAddress;
+    ULONG  ul2ndVideoMemorySize;
+
+    PUCHAR pj2ndIOAddress;
+/*#ifndef WIN2000
+    XGIIOADDRESS pjIOAddress;   //  base I/O address of VGA ports (0x3B0)
+#endif */
+    UCHAR  jChipType;            /* Used to Identify Graphics Chip */
+                                 /* defined in the data structure type  */
+                                 /* "XGI_CHIP_TYPE" */
+
+    UCHAR  jChipRevision;        /* Used to Identify Graphics Chip Revision */
+
+    UCHAR  ujVBChipID;           /* the ID of video bridge */
+                                 /* defined in the data structure type */
+                                 /* "XGI_VB_CHIP_TYPE" */
+
+    BOOLEAN    bNewScratch;
+
+    ULONG  ulCRT2LCDType;        /* defined in the data structure type */
+
+    ULONG usExternalChip;       /* NO VB or other video bridge (other than  */
+                                 /*  video bridge) */
+
+    BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
+
+    BOOLEAN bSkipDramSizing;     /* True: Skip video memory sizing. */
+
+    BOOLEAN bSkipSense;
+
+    BOOLEAN bIsPowerSaving;     /* True: XGIInit() is invoked by power management,
+                                   otherwise by 2nd adapter's initialzation */
+
+    PXGI_DSReg  pSR;             /* restore SR registers in initial function. */
+                                 /* end data :(idx, val) =  (FF, FF). */
+                                 /* Note : restore SR registers if  */
+                                 /* bSkipDramSizing = TRUE */
+
+    PXGI_DSReg  pCR;             /* restore CR registers in initial function. */
+                                 /* end data :(idx, val) =  (FF, FF) */
+                                 /* Note : restore cR registers if  */
+                                 /* bSkipDramSizing = TRUE */
+/*
+#endif
+*/
+
+    PXGI_QUERYSPACE  pQueryVGAConfigSpace;
+
+    PXGI_QUERYSPACE  pQueryNorthBridgeSpace;
+
+    UCHAR  szVBIOSVer[VBIOS_VER_MAX_LENGTH];
+
+};
+#endif
+
+/* Addtional IOCTL for communication xgifb <> X driver        */
+/* If changing this, xgifb.h must also be changed (for xgifb) */
+
+#ifdef LINUX_XF86  /* We don't want the X driver to depend on the kernel source */
+
+/* ioctl for identifying and giving some info (esp. memory heap start) */
+#define XGIFB_GET_INFO    0x80046ef8  /* Wow, what a terrible hack... */
+
+/* Structure argument for XGIFB_GET_INFO ioctl  */
+typedef struct _XGIFB_INFO xgifb_info, *pxgifb_info;
+
+struct _XGIFB_INFO {
+       CARD32  xgifb_id;               /* for identifying xgifb */
+#ifndef XGIFB_ID
+#define XGIFB_ID         0x53495346    /* Identify myself with 'XGIF' */
+#endif
+       CARD32  chip_id;                /* PCI ID of detected chip */
+       CARD32  memory;                 /* video memory in KB which xgifb manages */
+       CARD32  heapstart;              /* heap start (= xgifb "mem" argument) in KB */
+       CARD8   fbvidmode;              /* current xgifb mode */
+
+       CARD8   xgifb_version;
+       CARD8   xgifb_revision;
+       CARD8   xgifb_patchlevel;
+
+       CARD8   xgifb_caps;             /* xgifb's capabilities */
+
+       CARD32  xgifb_tqlen;            /* turbo queue length (in KB) */
+
+       CARD32  xgifb_pcibus;           /* The card's PCI ID */
+       CARD32  xgifb_pcislot;
+       CARD32  xgifb_pcifunc;
+
+       CARD8   xgifb_lcdpdc;
+
+       CARD8   xgifb_lcda;
+
+       CARD32  xgifb_vbflags;
+       CARD32  xgifb_currentvbflags;
+
+       CARD32  xgifb_scalelcd;
+       CARD32  xgifb_specialtiming;
+
+       CARD8   xgifb_haveemi;
+       CARD8   xgifb_emi30,xgifb_emi31,xgifb_emi32,xgifb_emi33;
+       CARD8   xgifb_haveemilcd;
+
+       CARD8   xgifb_lcdpdca;
+
+       CARD8 reserved[212];            /* for future use */
+};
+#endif
+
+#endif
+
index 0c2f14ff96968e9e910d353662932727177d9367..61d75507d5d0e8f385019f0917ef8f4f6b726ecb 100644 (file)
@@ -1201,7 +1201,7 @@ made_compressed_probe:
                if (rcv->urb == NULL) {
                        dev_dbg(&intf->dev,
                                "out of memory (read urbs usb_alloc_urb)\n");
-                       goto alloc_fail7;
+                       goto alloc_fail6;
                }
 
                rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -1225,7 +1225,7 @@ made_compressed_probe:
                if (snd->urb == NULL) {
                        dev_dbg(&intf->dev,
                                "out of memory (write urbs usb_alloc_urb)");
-                       goto alloc_fail7;
+                       goto alloc_fail8;
                }
 
                if (usb_endpoint_xfer_int(epwrite))
@@ -1264,6 +1264,7 @@ made_compressed_probe:
                i = device_create_file(&intf->dev,
                                                &dev_attr_iCountryCodeRelDate);
                if (i < 0) {
+                       device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
                        kfree(acm->country_codes);
                        goto skip_countries;
                }
@@ -1300,6 +1301,7 @@ alloc_fail8:
                usb_free_urb(acm->wb[i].urb);
 alloc_fail7:
        acm_read_buffers_free(acm);
+alloc_fail6:
        for (i = 0; i < num_rx_buf; i++)
                usb_free_urb(acm->ru[i].urb);
        usb_free_urb(acm->ctrlurb);
index ded550eda5d967fbd2f91f34fab08458cf964d89..a6bd53ace03565a6a1131168b240c56f4974ecb4 100644 (file)
@@ -1272,8 +1272,7 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
 
 static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
 {
-       int                     w, i;
-       struct usb_interface    *intf;
+       int     w;
 
        /* Remote wakeup is needed only when we actually go to sleep.
         * For things like FREEZE and QUIESCE, if the device is already
@@ -1285,16 +1284,10 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
                return;
        }
 
-       /* If remote wakeup is permitted, see whether any interface drivers
+       /* Enable remote wakeup if it is allowed, even if no interface drivers
         * actually want it.
         */
-       w = 0;
-       if (device_may_wakeup(&udev->dev) && udev->actconfig) {
-               for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-                       intf = udev->actconfig->interface[i];
-                       w |= intf->needs_remote_wakeup;
-               }
-       }
+       w = device_may_wakeup(&udev->dev);
 
        /* If the device is autosuspended with the wrong wakeup setting,
         * autoresume now so the setting can be changed.
@@ -1328,6 +1321,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
 
        /* For all other calls, take the device back to full power and
         * tell the PM core in case it was autosuspended previously.
+        * Unbind the interfaces that will need rebinding later.
         */
        } else {
                status = usb_resume_both(udev, msg);
@@ -1336,6 +1330,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
                        pm_runtime_set_active(dev);
                        pm_runtime_enable(dev);
                        udev->last_busy = jiffies;
+                       do_unbind_rebind(udev, DO_REBIND);
                }
        }
 
index a73e08fdab36336fee6f14bacef1c7dd1ec58764..fd4c36ea5e4688971afc9c2f32e3668429d0ae63 100644 (file)
@@ -416,8 +416,11 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
                        /* A length of zero means transfer the whole sg list */
                        len = length;
                        if (len == 0) {
-                               for_each_sg(sg, sg, nents, i)
-                                       len += sg->length;
+                               struct scatterlist      *sg2;
+                               int                     j;
+
+                               for_each_sg(sg, sg2, nents, j)
+                                       len += sg2->length;
                        }
                } else {
                        /*
index 649c0c5f7158d57cf1bdc3d7c382a10330cc4f63..591ae9fde1993db406d32626cf1aac3df9c36b57 100644 (file)
@@ -295,6 +295,7 @@ config USB_GADGET_S3C_HSOTG
        boolean "S3C HS/OtG USB Device controller"
        depends on S3C_DEV_USB_HSOTG
        select USB_GADGET_S3C_HSOTG_PIO
+       select USB_GADGET_DUALSPEED
        help
          The Samsung S3C64XX USB2.0 high-speed gadget controller
          integrated into the S3C64XX series SoC.
index 43bf44514c417d0431b52604569bef796871248b..b91115f84b137e69b539b6c09a6f76de2afc3dc0 100644 (file)
@@ -101,7 +101,7 @@ static struct uac_feature_unit_descriptor_0 feature_unit_desc = {
 static struct usb_audio_control mute_control = {
        .list = LIST_HEAD_INIT(mute_control.list),
        .name = "Mute Control",
-       .type = UAC_MUTE_CONTROL,
+       .type = UAC_FU_MUTE,
        /* Todo: add real Mute control code */
        .set = generic_set_cmd,
        .get = generic_get_cmd,
@@ -110,7 +110,7 @@ static struct usb_audio_control mute_control = {
 static struct usb_audio_control volume_control = {
        .list = LIST_HEAD_INIT(volume_control.list),
        .name = "Volume Control",
-       .type = UAC_VOLUME_CONTROL,
+       .type = UAC_FU_VOLUME,
        /* Todo: add real Volume control code */
        .set = generic_set_cmd,
        .get = generic_get_cmd,
index 38226e9a371d2d39dcb932a64144372545e75542..95dd4662d6a83acb3153433713c3e48889500f69 100644 (file)
@@ -469,8 +469,7 @@ static int eem_unwrap(struct gether *port,
                                crc = get_unaligned_le32(skb->data + len
                                                        - ETH_FCS_LEN);
                                crc2 = ~crc32_le(~0,
-                                               skb->data,
-                                               skb->len - ETH_FCS_LEN);
+                                               skb->data, len - ETH_FCS_LEN);
                        } else {
                                crc = get_unaligned_be32(skb->data + len
                                                        - ETH_FCS_LEN);
index 7d05a0be5c600c0bc6e3b2beaae8e25298aa7ea2..4ce899c9b1653b2cfd747e65a17b919d0adeae2c 100644 (file)
@@ -321,8 +321,8 @@ struct fsg_dev;
 /* Data shared by all the FSG instances. */
 struct fsg_common {
        struct usb_gadget       *gadget;
-       struct fsg_dev          *fsg;
-       struct fsg_dev          *prev_fsg;
+       struct fsg_dev          *fsg, *new_fsg;
+       wait_queue_head_t       fsg_wait;
 
        /* filesem protects: backing files in use */
        struct rw_semaphore     filesem;
@@ -351,7 +351,6 @@ struct fsg_common {
        enum fsg_state          state;          /* For exception handling */
        unsigned int            exception_req_tag;
 
-       u8                      config, new_config;
        enum data_direction     data_dir;
        u32                     data_size;
        u32                     data_size_from_cmnd;
@@ -595,7 +594,7 @@ static int fsg_setup(struct usb_function *f,
        u16                     w_value = le16_to_cpu(ctrl->wValue);
        u16                     w_length = le16_to_cpu(ctrl->wLength);
 
-       if (!fsg->common->config)
+       if (!fsg_is_set(fsg->common))
                return -EOPNOTSUPP;
 
        switch (ctrl->bRequest) {
@@ -2303,24 +2302,20 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
        return -ENOMEM;
 }
 
-/*
- * Reset interface setting and re-init endpoint state (toggle etc).
- * Call with altsetting < 0 to disable the interface.  The only other
- * available altsetting is 0, which enables the interface.
- */
-static int do_set_interface(struct fsg_common *common, int altsetting)
+/* Reset interface setting and re-init endpoint state (toggle etc). */
+static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
 {
-       int     rc = 0;
-       int     i;
-       const struct usb_endpoint_descriptor    *d;
+       const struct usb_endpoint_descriptor *d;
+       struct fsg_dev *fsg;
+       int i, rc = 0;
 
        if (common->running)
                DBG(common, "reset interface\n");
 
 reset:
        /* Deallocate the requests */
-       if (common->prev_fsg) {
-               struct fsg_dev *fsg = common->prev_fsg;
+       if (common->fsg) {
+               fsg = common->fsg;
 
                for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
                        struct fsg_buffhd *bh = &common->buffhds[i];
@@ -2345,88 +2340,53 @@ reset:
                        fsg->bulk_out_enabled = 0;
                }
 
-               common->prev_fsg = 0;
+               common->fsg = NULL;
+               wake_up(&common->fsg_wait);
        }
 
        common->running = 0;
-       if (altsetting < 0 || rc != 0)
+       if (!new_fsg || rc)
                return rc;
 
-       DBG(common, "set interface %d\n", altsetting);
+       common->fsg = new_fsg;
+       fsg = common->fsg;
 
-       if (fsg_is_set(common)) {
-               struct fsg_dev *fsg = common->fsg;
-               common->prev_fsg = common->fsg;
+       /* Enable the endpoints */
+       d = fsg_ep_desc(common->gadget,
+                       &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
+       rc = enable_endpoint(common, fsg->bulk_in, d);
+       if (rc)
+               goto reset;
+       fsg->bulk_in_enabled = 1;
+
+       d = fsg_ep_desc(common->gadget,
+                       &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
+       rc = enable_endpoint(common, fsg->bulk_out, d);
+       if (rc)
+               goto reset;
+       fsg->bulk_out_enabled = 1;
+       common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
+       clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
 
-               /* Enable the endpoints */
-               d = fsg_ep_desc(common->gadget,
-                               &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
-               rc = enable_endpoint(common, fsg->bulk_in, d);
+       /* Allocate the requests */
+       for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
+               struct fsg_buffhd       *bh = &common->buffhds[i];
+
+               rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
                if (rc)
                        goto reset;
-               fsg->bulk_in_enabled = 1;
-
-               d = fsg_ep_desc(common->gadget,
-                               &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
-               rc = enable_endpoint(common, fsg->bulk_out, d);
+               rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
                if (rc)
                        goto reset;
-               fsg->bulk_out_enabled = 1;
-               common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
-               clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-
-               /* Allocate the requests */
-               for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
-                       struct fsg_buffhd       *bh = &common->buffhds[i];
-
-                       rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
-                       if (rc)
-                               goto reset;
-                       rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
-                       if (rc)
-                               goto reset;
-                       bh->inreq->buf = bh->outreq->buf = bh->buf;
-                       bh->inreq->context = bh->outreq->context = bh;
-                       bh->inreq->complete = bulk_in_complete;
-                       bh->outreq->complete = bulk_out_complete;
-               }
-
-               common->running = 1;
-               for (i = 0; i < common->nluns; ++i)
-                       common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
-               return rc;
-       } else {
-               return -EIO;
-       }
-}
-
-
-/*
- * Change our operational configuration.  This code must agree with the code
- * that returns config descriptors, and with interface altsetting code.
- *
- * It's also responsible for power management interactions.  Some
- * configurations might not work with our current power sources.
- * For now we just assume the gadget is always self-powered.
- */
-static int do_set_config(struct fsg_common *common, u8 new_config)
-{
-       int     rc = 0;
-
-       /* Disable the single interface */
-       if (common->config != 0) {
-               DBG(common, "reset config\n");
-               common->config = 0;
-               rc = do_set_interface(common, -1);
+               bh->inreq->buf = bh->outreq->buf = bh->buf;
+               bh->inreq->context = bh->outreq->context = bh;
+               bh->inreq->complete = bulk_in_complete;
+               bh->outreq->complete = bulk_out_complete;
        }
 
-       /* Enable the interface */
-       if (new_config != 0) {
-               common->config = new_config;
-               rc = do_set_interface(common, 0);
-               if (rc != 0)
-                       common->config = 0;     /* Reset on errors */
-       }
+       common->running = 1;
+       for (i = 0; i < common->nluns; ++i)
+               common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
        return rc;
 }
 
@@ -2437,9 +2397,7 @@ static int do_set_config(struct fsg_common *common, u8 new_config)
 static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 {
        struct fsg_dev *fsg = fsg_from_func(f);
-       fsg->common->prev_fsg = fsg->common->fsg;
-       fsg->common->fsg = fsg;
-       fsg->common->new_config = 1;
+       fsg->common->new_fsg = fsg;
        raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
        return 0;
 }
@@ -2447,9 +2405,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 static void fsg_disable(struct usb_function *f)
 {
        struct fsg_dev *fsg = fsg_from_func(f);
-       fsg->common->prev_fsg = fsg->common->fsg;
-       fsg->common->fsg = fsg;
-       fsg->common->new_config = 0;
+       fsg->common->new_fsg = NULL;
        raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
 }
 
@@ -2459,19 +2415,17 @@ static void fsg_disable(struct usb_function *f)
 static void handle_exception(struct fsg_common *common)
 {
        siginfo_t               info;
-       int                     sig;
        int                     i;
        struct fsg_buffhd       *bh;
        enum fsg_state          old_state;
-       u8                      new_config;
        struct fsg_lun          *curlun;
        unsigned int            exception_req_tag;
-       int                     rc;
 
        /* Clear the existing signals.  Anything but SIGUSR1 is converted
         * into a high-priority EXIT exception. */
        for (;;) {
-               sig = dequeue_signal_lock(current, &current->blocked, &info);
+               int sig =
+                       dequeue_signal_lock(current, &current->blocked, &info);
                if (!sig)
                        break;
                if (sig != SIGUSR1) {
@@ -2482,7 +2436,7 @@ static void handle_exception(struct fsg_common *common)
        }
 
        /* Cancel all the pending transfers */
-       if (fsg_is_set(common)) {
+       if (likely(common->fsg)) {
                for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
                        bh = &common->buffhds[i];
                        if (bh->inreq_busy)
@@ -2523,7 +2477,6 @@ static void handle_exception(struct fsg_common *common)
        common->next_buffhd_to_fill = &common->buffhds[0];
        common->next_buffhd_to_drain = &common->buffhds[0];
        exception_req_tag = common->exception_req_tag;
-       new_config = common->new_config;
        old_state = common->state;
 
        if (old_state == FSG_STATE_ABORT_BULK_OUT)
@@ -2573,12 +2526,12 @@ static void handle_exception(struct fsg_common *common)
                break;
 
        case FSG_STATE_CONFIG_CHANGE:
-               rc = do_set_config(common, new_config);
+               do_set_interface(common, common->new_fsg);
                break;
 
        case FSG_STATE_EXIT:
        case FSG_STATE_TERMINATED:
-               do_set_config(common, 0);               /* Free resources */
+               do_set_interface(common, NULL);         /* Free resources */
                spin_lock_irq(&common->lock);
                common->state = FSG_STATE_TERMINATED;   /* Stop the thread */
                spin_unlock_irq(&common->lock);
@@ -2863,6 +2816,7 @@ buffhds_first_it:
                goto error_release;
        }
        init_completion(&common->thread_notifier);
+       init_waitqueue_head(&common->fsg_wait);
 #undef OR
 
 
@@ -2957,9 +2911,17 @@ static void fsg_common_release(struct kref *ref)
 static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
 {
        struct fsg_dev          *fsg = fsg_from_func(f);
+       struct fsg_common       *common = fsg->common;
 
        DBG(fsg, "unbind\n");
-       fsg_common_put(fsg->common);
+       if (fsg->common->fsg == fsg) {
+               fsg->common->new_fsg = NULL;
+               raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+               /* FIXME: make interruptible or killable somehow? */
+               wait_event(common->fsg_wait, common->fsg != fsg);
+       }
+
+       fsg_common_put(common);
        usb_free_descriptors(fsg->function.descriptors);
        usb_free_descriptors(fsg->function.hs_descriptors);
        kfree(fsg);
@@ -2970,7 +2932,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
 {
        struct fsg_dev          *fsg = fsg_from_func(f);
        struct usb_gadget       *gadget = c->cdev->gadget;
-       int                     rc;
        int                     i;
        struct usb_ep           *ep;
 
@@ -2996,6 +2957,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
        ep->driver_data = fsg->common;  /* claim the endpoint */
        fsg->bulk_out = ep;
 
+       /* Copy descriptors */
+       f->descriptors = usb_copy_descriptors(fsg_fs_function);
+       if (unlikely(!f->descriptors))
+               return -ENOMEM;
+
        if (gadget_is_dualspeed(gadget)) {
                /* Assume endpoint addresses are the same for both speeds */
                fsg_hs_bulk_in_desc.bEndpointAddress =
@@ -3003,16 +2969,17 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
                fsg_hs_bulk_out_desc.bEndpointAddress =
                        fsg_fs_bulk_out_desc.bEndpointAddress;
                f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
-               if (unlikely(!f->hs_descriptors))
+               if (unlikely(!f->hs_descriptors)) {
+                       usb_free_descriptors(f->descriptors);
                        return -ENOMEM;
+               }
        }
 
        return 0;
 
 autoconf_fail:
        ERROR(fsg, "unable to autoconfigure all endpoints\n");
-       rc = -ENOTSUPP;
-       return rc;
+       return -ENOTSUPP;
 }
 
 
@@ -3036,11 +3003,6 @@ static int fsg_add(struct usb_composite_dev *cdev,
 
        fsg->function.name        = FSG_DRIVER_DESC;
        fsg->function.strings     = fsg_strings_array;
-       fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function);
-       if (unlikely(!fsg->function.descriptors)) {
-               rc = -ENOMEM;
-               goto error_free_fsg;
-       }
        fsg->function.bind        = fsg_bind;
        fsg->function.unbind      = fsg_unbind;
        fsg->function.setup       = fsg_setup;
@@ -3056,19 +3018,9 @@ static int fsg_add(struct usb_composite_dev *cdev,
 
        rc = usb_add_function(c, &fsg->function);
        if (unlikely(rc))
-               goto error_free_all;
-
-       fsg_common_get(fsg->common);
-       return 0;
-
-error_free_all:
-       usb_free_descriptors(fsg->function.descriptors);
-       /* fsg_bind() might have copied those; or maybe not? who cares
-        * -- free it just in case. */
-       usb_free_descriptors(fsg->function.hs_descriptors);
-error_free_fsg:
-       kfree(fsg);
-
+               kfree(fsg);
+       else
+               fsg_common_get(fsg->common);
        return rc;
 }
 
index 2928523268b53ac61470959ac6d6cd41519633d1..82506ca297d5f1632312f8d52b7f80b7aab49637 100644 (file)
@@ -2400,7 +2400,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver);
 static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev)
 {
        struct qe_udc *udc;
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        unsigned int tmp_addr = 0;
        struct usb_device_para __iomem *usbpram;
        unsigned int i;
@@ -2525,7 +2525,7 @@ static void qe_udc_release(struct device *dev)
 static int __devinit qe_udc_probe(struct of_device *ofdev,
                        const struct of_device_id *match)
 {
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct qe_ep *ep;
        unsigned int ret = 0;
        unsigned int i;
index 4b0e4a040d6f7a1c134404ef253c3756caf85388..d1af253a910591fabacf1669a66749b5dbc7e1f5 100644 (file)
@@ -392,6 +392,17 @@ static int __gfs_do_config(struct usb_configuration *c,
        if (unlikely(ret < 0))
                return ret;
 
+       /* After previous do_configs there may be some invalid
+        * pointers in c->interface array.  This happens every time
+        * a user space function with fewer interfaces than a user
+        * space function that was run before the new one is run.  The
+        * compasit's set_config() assumes that if there is no more
+        * then MAX_CONFIG_INTERFACES interfaces in a configuration
+        * then there is a NULL pointer after the last interface in
+        * c->interface array.  We need to make sure this is true. */
+       if (c->next_interface_id < ARRAY_SIZE(c->interface))
+               c->interface[c->next_interface_id] = NULL;
+
        return 0;
 }
 
index 8b960deed68069baf74cbfce86415450373ca001..c3caf1ac73ce4fc794ca7e47820ecf461bbcac70 100644 (file)
@@ -537,35 +537,35 @@ struct m66592 {
 /*-------------------------------------------------------------------------*/
 static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset)
 {
-       return inw((unsigned long)m66592->reg + offset);
+       return ioread16(m66592->reg + offset);
 }
 
 static inline void m66592_read_fifo(struct m66592 *m66592,
                unsigned long offset,
                void *buf, unsigned long len)
 {
-       unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+       void __iomem *fifoaddr = m66592->reg + offset;
 
        if (m66592->pdata->on_chip) {
                len = (len + 3) / 4;
-               insl(fifoaddr, buf, len);
+               ioread32_rep(fifoaddr, buf, len);
        } else {
                len = (len + 1) / 2;
-               insw(fifoaddr, buf, len);
+               ioread16_rep(fifoaddr, buf, len);
        }
 }
 
 static inline void m66592_write(struct m66592 *m66592, u16 val,
                                unsigned long offset)
 {
-       outw(val, (unsigned long)m66592->reg + offset);
+       iowrite16(val, m66592->reg + offset);
 }
 
 static inline void m66592_write_fifo(struct m66592 *m66592,
                unsigned long offset,
                void *buf, unsigned long len)
 {
-       unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+       void __iomem *fifoaddr = m66592->reg + offset;
 
        if (m66592->pdata->on_chip) {
                unsigned long count;
@@ -573,25 +573,25 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
                int i;
 
                count = len / 4;
-               outsl(fifoaddr, buf, count);
+               iowrite32_rep(fifoaddr, buf, count);
 
                if (len & 0x00000003) {
                        pb = buf + count * 4;
                        for (i = 0; i < (len & 0x00000003); i++) {
                                if (m66592_read(m66592, M66592_CFBCFG)) /* le */
-                                       outb(pb[i], fifoaddr + (3 - i));
+                                       iowrite8(pb[i], fifoaddr + (3 - i));
                                else
-                                       outb(pb[i], fifoaddr + i);
+                                       iowrite8(pb[i], fifoaddr + i);
                        }
                }
        } else {
                unsigned long odd = len & 0x0001;
 
                len = len / 2;
-               outsw(fifoaddr, buf, len);
+               iowrite16_rep(fifoaddr, buf, len);
                if (odd) {
                        unsigned char *p = buf + len*2;
-                       outb(*p, fifoaddr);
+                       iowrite8(*p, fifoaddr);
                }
        }
 }
index 43abf55d8c60fcbc7029d4a0d4545188b9ab4308..4c3ac5c422373e6494db8ff82c03cdb208d130ea 100644 (file)
@@ -82,7 +82,7 @@ static struct class *usb_gadget_class;
 struct printer_dev {
        spinlock_t              lock;           /* lock this structure */
        /* lock buffer lists during read/write calls */
-       spinlock_t              lock_printer_io;
+       struct mutex            lock_printer_io;
        struct usb_gadget       *gadget;
        struct usb_request      *req;           /* for control responses */
        u8                      config;
@@ -567,7 +567,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 
        DBG(dev, "printer_read trying to read %d bytes\n", (int)len);
 
-       spin_lock(&dev->lock_printer_io);
+       mutex_lock(&dev->lock_printer_io);
        spin_lock_irqsave(&dev->lock, flags);
 
        /* We will use this flag later to check if a printer reset happened
@@ -601,7 +601,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
                 * call or not.
                 */
                if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
                }
 
@@ -648,7 +648,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
                if (dev->reset_printer) {
                        list_add(&current_rx_req->list, &dev->rx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
                }
 
@@ -673,7 +673,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
        dev->current_rx_buf = current_rx_buf;
 
        spin_unlock_irqrestore(&dev->lock, flags);
-       spin_unlock(&dev->lock_printer_io);
+       mutex_unlock(&dev->lock_printer_io);
 
        DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);
 
@@ -697,7 +697,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        if (len == 0)
                return -EINVAL;
 
-       spin_lock(&dev->lock_printer_io);
+       mutex_lock(&dev->lock_printer_io);
        spin_lock_irqsave(&dev->lock, flags);
 
        /* Check if a printer reset happens while we have interrupts on */
@@ -713,7 +713,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                 * a NON-Blocking call or not.
                 */
                if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
                }
 
@@ -752,7 +752,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 
                if (copy_from_user(req->buf, buf, size)) {
                        list_add(&req->list, &dev->tx_reqs);
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return bytes_copied;
                }
 
@@ -766,14 +766,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                if (dev->reset_printer) {
                        list_add(&req->list, &dev->tx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
                }
 
                if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
                        list_add(&req->list, &dev->tx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
                }
 
@@ -782,7 +782,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        }
 
        spin_unlock_irqrestore(&dev->lock, flags);
-       spin_unlock(&dev->lock_printer_io);
+       mutex_unlock(&dev->lock_printer_io);
 
        DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
 
@@ -820,11 +820,11 @@ printer_poll(struct file *fd, poll_table *wait)
        unsigned long           flags;
        int                     status = 0;
 
-       spin_lock(&dev->lock_printer_io);
+       mutex_lock(&dev->lock_printer_io);
        spin_lock_irqsave(&dev->lock, flags);
        setup_rx_reqs(dev);
        spin_unlock_irqrestore(&dev->lock, flags);
-       spin_unlock(&dev->lock_printer_io);
+       mutex_unlock(&dev->lock_printer_io);
 
        poll_wait(fd, &dev->rx_wait, wait);
        poll_wait(fd, &dev->tx_wait, wait);
@@ -1461,7 +1461,7 @@ autoconf_fail:
        }
 
        spin_lock_init(&dev->lock);
-       spin_lock_init(&dev->lock_printer_io);
+       mutex_init(&dev->lock_printer_io);
        INIT_LIST_HEAD(&dev->tx_reqs);
        INIT_LIST_HEAD(&dev->tx_reqs_active);
        INIT_LIST_HEAD(&dev->rx_reqs);
@@ -1594,7 +1594,7 @@ cleanup(void)
 {
        int status;
 
-       spin_lock(&usb_printer_gadget.lock_printer_io);
+       mutex_lock(&usb_printer_gadget.lock_printer_io);
        class_destroy(usb_gadget_class);
        unregister_chrdev_region(g_printer_devno, 2);
 
@@ -1602,6 +1602,6 @@ cleanup(void)
        if (status)
                ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
 
-       spin_unlock(&usb_printer_gadget.lock_printer_io);
+       mutex_unlock(&usb_printer_gadget.lock_printer_io);
 }
 module_exit(cleanup);
index 888d8f166c0b1c9d4ddcac3fbf364935041458be..70a817842755484f5ee0b19e51db505b32532bf5 100644 (file)
@@ -1500,7 +1500,7 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
        struct r8a66597         *r8a66597 = dev_get_drvdata(&pdev->dev);
 
        del_timer_sync(&r8a66597->timer);
-       iounmap((void *)r8a66597->reg);
+       iounmap(r8a66597->reg);
        free_irq(platform_get_irq(pdev, 0), r8a66597);
        r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
 #ifdef CONFIG_HAVE_CLK
@@ -1578,7 +1578,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
        init_timer(&r8a66597->timer);
        r8a66597->timer.function = r8a66597_timer;
        r8a66597->timer.data = (unsigned long)r8a66597;
-       r8a66597->reg = (unsigned long)reg;
+       r8a66597->reg = reg;
 
 #ifdef CONFIG_HAVE_CLK
        if (r8a66597->pdata->on_chip) {
index 9a537aa07968d7b449972ba048a7d99d74f44d99..f763b5190afa2dfafb65c9b98da0ff9e62fcd7a4 100644 (file)
@@ -91,7 +91,7 @@ struct r8a66597_ep {
 
 struct r8a66597 {
        spinlock_t              lock;
-       unsigned long           reg;
+       void __iomem            *reg;
 
 #ifdef CONFIG_HAVE_CLK
        struct clk *clk;
@@ -127,7 +127,7 @@ struct r8a66597 {
 
 static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
 {
-       return inw(r8a66597->reg + offset);
+       return ioread16(r8a66597->reg + offset);
 }
 
 static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
@@ -135,7 +135,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
                                      unsigned char *buf,
                                      int len)
 {
-       unsigned long fifoaddr = r8a66597->reg + offset;
+       void __iomem *fifoaddr = r8a66597->reg + offset;
        unsigned int data;
        int i;
 
@@ -144,7 +144,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
 
                /* aligned buf case */
                if (len >= 4 && !((unsigned long)buf & 0x03)) {
-                       insl(fifoaddr, buf, len / 4);
+                       ioread32_rep(fifoaddr, buf, len / 4);
                        buf += len & ~0x03;
                        len &= 0x03;
                }
@@ -152,7 +152,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
                /* unaligned buf case */
                for (i = 0; i < len; i++) {
                        if (!(i & 0x03))
-                               data = inl(fifoaddr);
+                               data = ioread32(fifoaddr);
 
                        buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
                }
@@ -161,7 +161,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
 
                /* aligned buf case */
                if (len >= 2 && !((unsigned long)buf & 0x01)) {
-                       insw(fifoaddr, buf, len / 2);
+                       ioread16_rep(fifoaddr, buf, len / 2);
                        buf += len & ~0x01;
                        len &= 0x01;
                }
@@ -169,7 +169,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
                /* unaligned buf case */
                for (i = 0; i < len; i++) {
                        if (!(i & 0x01))
-                               data = inw(fifoaddr);
+                               data = ioread16(fifoaddr);
 
                        buf[i] = (data >> ((i & 0x01) * 8)) & 0xff;
                }
@@ -179,7 +179,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
 static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
                                  unsigned long offset)
 {
-       outw(val, r8a66597->reg + offset);
+       iowrite16(val, r8a66597->reg + offset);
 }
 
 static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
@@ -187,21 +187,21 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
                                       unsigned char *buf,
                                       int len)
 {
-       unsigned long fifoaddr = r8a66597->reg + offset;
+       void __iomem *fifoaddr = r8a66597->reg + offset;
        int adj = 0;
        int i;
 
        if (r8a66597->pdata->on_chip) {
                /* 32-bit access only if buf is 32-bit aligned */
                if (len >= 4 && !((unsigned long)buf & 0x03)) {
-                       outsl(fifoaddr, buf, len / 4);
+                       iowrite32_rep(fifoaddr, buf, len / 4);
                        buf += len & ~0x03;
                        len &= 0x03;
                }
        } else {
                /* 16-bit access only if buf is 16-bit aligned */
                if (len >= 2 && !((unsigned long)buf & 0x01)) {
-                       outsw(fifoaddr, buf, len / 2);
+                       iowrite16_rep(fifoaddr, buf, len / 2);
                        buf += len & ~0x01;
                        len &= 0x01;
                }
@@ -216,7 +216,7 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
        }
 
        for (i = 0; i < len; i++)
-               outb(buf[i], fifoaddr + adj - (i & adj));
+               iowrite8(buf[i], fifoaddr + adj - (i & adj));
 }
 
 static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
index 1f73b485732d1b74028064e37193ce6f56021718..26193eceb3231d48c06e98b29a09cf9849b319f5 100644 (file)
@@ -297,6 +297,12 @@ static void s3c_hsotg_ctrl_epint(struct s3c_hsotg *hsotg,
  */
 static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
 {
+       unsigned int ep;
+       unsigned int addr;
+       unsigned int size;
+       int timeout;
+       u32 val;
+
        /* the ryu 2.6.24 release ahs
           writel(0x1C0, hsotg->regs + S3C_GRXFSIZ);
           writel(S3C_GNPTXFSIZ_NPTxFStAddr(0x200) |
@@ -310,6 +316,51 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
        writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) |
               S3C_GNPTXFSIZ_NPTxFDep(0x1C0),
               hsotg->regs + S3C_GNPTXFSIZ);
+
+       /* arange all the rest of the TX FIFOs, as some versions of this
+        * block have overlapping default addresses. This also ensures
+        * that if the settings have been changed, then they are set to
+        * known values. */
+
+       /* start at the end of the GNPTXFSIZ, rounded up */
+       addr = 2048 + 1024;
+       size = 768;
+
+       /* currently we allocate TX FIFOs for all possible endpoints,
+        * and assume that they are all the same size. */
+
+       for (ep = 0; ep <= 15; ep++) {
+               val = addr;
+               val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT;
+               addr += size;
+
+               writel(val, hsotg->regs + S3C_DPTXFSIZn(ep));
+       }
+
+       /* according to p428 of the design guide, we need to ensure that
+        * all fifos are flushed before continuing */
+
+       writel(S3C_GRSTCTL_TxFNum(0x10) | S3C_GRSTCTL_TxFFlsh |
+              S3C_GRSTCTL_RxFFlsh, hsotg->regs + S3C_GRSTCTL);
+
+       /* wait until the fifos are both flushed */
+       timeout = 100;
+       while (1) {
+               val = readl(hsotg->regs + S3C_GRSTCTL);
+
+               if ((val & (S3C_GRSTCTL_TxFFlsh | S3C_GRSTCTL_RxFFlsh)) == 0)
+                       break;
+
+               if (--timeout == 0) {
+                       dev_err(hsotg->dev,
+                               "%s: timeout flushing fifos (GRSTCTL=%08x)\n",
+                               __func__, val);
+               }
+
+               udelay(1);
+       }
+
+       dev_dbg(hsotg->dev, "FIFOs reset, timeout at %d\n", timeout);
 }
 
 /**
@@ -2574,6 +2625,9 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
        writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK,
               hsotg->regs + S3C_DCTL);
 
+       /* must be at-least 3ms to allow bus to see disconnect */
+       msleep(3);
+
        /* remove the soft-disconnect and let's go */
        __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
 
@@ -2730,6 +2784,9 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
 
        writel(0, hsotg->regs + S3C_DAINTMSK);
 
+       /* Be in disconnected state until gadget is registered */
+       __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
+
        if (0) {
                /* post global nak until we're ready */
                writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak,
index d5f4c1d45c9703add01e29e582e5f705e87cc83f..e724a051bfdd11bcd520ae90ff0b0c448883d13f 100644 (file)
@@ -1700,9 +1700,13 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
        if (!driver || driver != udc->driver || !driver->unbind)
                return -EINVAL;
 
-       dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",
+       dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n",
                driver->driver.name);
 
+       /* report disconnect */
+       if (driver->disconnect)
+               driver->disconnect(&udc->gadget);
+
        driver->unbind(&udc->gadget);
 
        device_del(&udc->gadget.dev);
index 16bdf77f582a02526f2b60750e26dbfb2e425228..3e8dcb5455e3a4912f7bc0fc525b69c524cade7f 100644 (file)
@@ -536,17 +536,11 @@ recycle:
                list_move(&req->list, &port->read_pool);
        }
 
-       /* Push from tty to ldisc; this is immediate with low_latency, and
-        * may trigger callbacks to this driver ... so drop the spinlock.
+       /* Push from tty to ldisc; without low_latency set this is handled by
+        * a workqueue, so we won't get callbacks and can hold port_lock
         */
        if (tty && do_push) {
-               spin_unlock_irq(&port->port_lock);
                tty_flip_buffer_push(tty);
-               wake_up_interruptible(&tty->read_wait);
-               spin_lock_irq(&port->port_lock);
-
-               /* tty may have been closed */
-               tty = port->port_tty;
        }
 
 
@@ -784,11 +778,6 @@ static int gs_open(struct tty_struct *tty, struct file *file)
        port->open_count = 1;
        port->openclose = false;
 
-       /* low_latency means ldiscs work in tasklet context, without
-        * needing a workqueue schedule ... easier to keep up.
-        */
-       tty->low_latency = 1;
-
        /* if connected, start the I/O stream */
        if (port->port_usb) {
                struct gserial  *gser = port->port_usb;
@@ -1195,6 +1184,7 @@ void gserial_cleanup(void)
        n_ports = 0;
 
        tty_unregister_driver(gs_tty_driver);
+       put_tty_driver(gs_tty_driver);
        gs_tty_driver = NULL;
 
        pr_debug("%s: cleaned up ttyGS* support\n", __func__);
index ef3e88f0b3c307c0d605ad6f77b70407e90ae829..a3ef2a9d9dc2793c127994838abdd13eb8248b3f 100644 (file)
@@ -1135,7 +1135,7 @@ MODULE_LICENSE ("GPL");
 
 #ifdef CONFIG_XPS_USB_HCD_XILINX
 #include "ehci-xilinx-of.c"
-#define OF_PLATFORM_DRIVER     ehci_hcd_xilinx_of_driver
+#define XILINX_OF_PLATFORM_DRIVER      ehci_hcd_xilinx_of_driver
 #endif
 
 #ifdef CONFIG_PLAT_ORION
@@ -1159,7 +1159,8 @@ MODULE_LICENSE ("GPL");
 #endif
 
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
-    !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
+    !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
+    !defined(XILINX_OF_PLATFORM_DRIVER)
 #error "missing bus glue for ehci-hcd"
 #endif
 
@@ -1213,10 +1214,20 @@ static int __init ehci_hcd_init(void)
        if (retval < 0)
                goto clean3;
 #endif
+
+#ifdef XILINX_OF_PLATFORM_DRIVER
+       retval = of_register_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
+       if (retval < 0)
+               goto clean4;
+#endif
        return retval;
 
+#ifdef XILINX_OF_PLATFORM_DRIVER
+       /* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */
+clean4:
+#endif
 #ifdef OF_PLATFORM_DRIVER
-       /* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */
+       of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
 clean3:
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
@@ -1243,6 +1254,9 @@ module_init(ehci_hcd_init);
 
 static void __exit ehci_hcd_cleanup(void)
 {
+#ifdef XILINX_OF_PLATFORM_DRIVER
+       of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
+#endif
 #ifdef OF_PLATFORM_DRIVER
        of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
 #endif
index 544ccfd7056ed5ff13d7a3daea6178d22e9efbd6..bd4027745aa7039e5cfcdd6b1bf4057ad8569d85 100644 (file)
@@ -207,10 +207,17 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
        /* Initialize the transceiver */
        if (pdata->otg) {
                pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
-               if (otg_init(pdata->otg) != 0)
-                       dev_err(dev, "unable to init transceiver\n");
-               else if (otg_set_vbus(pdata->otg, 1) != 0)
+               ret = otg_init(pdata->otg);
+               if (ret) {
+                       dev_err(dev, "unable to init transceiver, probably missing\n");
+                       ret = -ENODEV;
+                       goto err_add;
+               }
+               ret = otg_set_vbus(pdata->otg, 1);
+               if (ret) {
                        dev_err(dev, "unable to enable vbus on transceiver\n");
+                       goto err_add;
+               }
        }
 
        priv->hcd = hcd;
index 013972bbde57d21bd16c737c1a1e455a1f90876a..4899f451add98f5727cd72710ea8f4751070d868 100644 (file)
@@ -151,7 +151,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
 static int __devinit
 ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match)
 {
-       struct device_node *dn = op->node;
+       struct device_node *dn = op->dev.of_node;
        struct usb_hcd *hcd;
        struct ehci_hcd *ehci;
        struct resource res;
index 20a0dfe0fe368c7f6284f82df2080e19b69935a8..0587ad4ce5c2948500dbd339b5d03f322b905fb6 100644 (file)
@@ -2224,12 +2224,9 @@ static void remove_debug_file(struct isp1362_hcd *isp1362_hcd)
 
 /*-------------------------------------------------------------------------*/
 
-static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
+static void __isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
 {
        int tmp = 20;
-       unsigned long flags;
-
-       spin_lock_irqsave(&isp1362_hcd->lock, flags);
 
        isp1362_write_reg16(isp1362_hcd, HCSWRES, HCSWRES_MAGIC);
        isp1362_write_reg32(isp1362_hcd, HCCMDSTAT, OHCI_HCR);
@@ -2240,6 +2237,14 @@ static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
        }
        if (!tmp)
                pr_err("Software reset timeout\n");
+}
+
+static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&isp1362_hcd->lock, flags);
+       __isp1362_sw_reset(isp1362_hcd);
        spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
 }
 
@@ -2418,7 +2423,7 @@ static void isp1362_hc_stop(struct usb_hcd *hcd)
        if (isp1362_hcd->board && isp1362_hcd->board->reset)
                isp1362_hcd->board->reset(hcd->self.controller, 1);
        else
-               isp1362_sw_reset(isp1362_hcd);
+               __isp1362_sw_reset(isp1362_hcd);
 
        if (isp1362_hcd->board && isp1362_hcd->board->clock)
                isp1362_hcd->board->clock(hcd->self.controller, 0);
index 5151516ea1dee98a093b35cee1b89f4bca3cd457..d995351f9bed8cf31d07fb9163a328f22cf88aa6 100644 (file)
@@ -65,7 +65,7 @@ static inline void delayed_insw(unsigned int addr, void *buf, int len)
        unsigned short *bp = (unsigned short *)buf;
        while (len--) {
                DUMMY_DELAY_ACCESS;
-               *bp++ = inw((void *)addr);
+               *bp++ = inw(addr);
        }
 }
 
index 6db57ab6079d31a7a6a2d107834ba42eeeec9839..77be3c24a4279d0aca3cc268164cf20960e135f5 100644 (file)
@@ -1065,7 +1065,7 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)
        else if (speed == LSMODE)
                rh->port |= USB_PORT_STAT_LOW_SPEED;
 
-       rh->port &= USB_PORT_STAT_RESET;
+       rh->port &= ~USB_PORT_STAT_RESET;
        rh->port |= USB_PORT_STAT_ENABLE;
 }
 
@@ -2404,7 +2404,7 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev)
 
        del_timer_sync(&r8a66597->rh_timer);
        usb_remove_hcd(hcd);
-       iounmap((void *)r8a66597->reg);
+       iounmap(r8a66597->reg);
 #ifdef CONFIG_HAVE_CLK
        if (r8a66597->pdata->on_chip)
                clk_put(r8a66597->clk);
@@ -2496,7 +2496,7 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
        init_timer(&r8a66597->rh_timer);
        r8a66597->rh_timer.function = r8a66597_timer;
        r8a66597->rh_timer.data = (unsigned long)r8a66597;
-       r8a66597->reg = (unsigned long)reg;
+       r8a66597->reg = reg;
 
        /* make sure no interrupts are pending */
        ret = r8a66597_clock_enable(r8a66597);
index 228e3fb23854e7b3fe0f403c360f1fdb0bdf7414..95d0f5adfdcff9d2c67dcb327507dd192d5903f1 100644 (file)
@@ -112,7 +112,7 @@ struct r8a66597_root_hub {
 
 struct r8a66597 {
        spinlock_t lock;
-       unsigned long reg;
+       void __iomem *reg;
 #ifdef CONFIG_HAVE_CLK
        struct clk *clk;
 #endif
@@ -170,67 +170,67 @@ static inline struct urb *r8a66597_get_urb(struct r8a66597 *r8a66597,
 
 static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
 {
-       return inw(r8a66597->reg + offset);
+       return ioread16(r8a66597->reg + offset);
 }
 
 static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
                                      unsigned long offset, u16 *buf,
                                      int len)
 {
-       unsigned long fifoaddr = r8a66597->reg + offset;
+       void __iomem *fifoaddr = r8a66597->reg + offset;
        unsigned long count;
 
        if (r8a66597->pdata->on_chip) {
                count = len / 4;
-               insl(fifoaddr, buf, count);
+               ioread32_rep(fifoaddr, buf, count);
 
                if (len & 0x00000003) {
-                       unsigned long tmp = inl(fifoaddr);
+                       unsigned long tmp = ioread32(fifoaddr);
                        memcpy((unsigned char *)buf + count * 4, &tmp,
                               len & 0x03);
                }
        } else {
                len = (len + 1) / 2;
-               insw(fifoaddr, buf, len);
+               ioread16_rep(fifoaddr, buf, len);
        }
 }
 
 static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
                                  unsigned long offset)
 {
-       outw(val, r8a66597->reg + offset);
+       iowrite16(val, r8a66597->reg + offset);
 }
 
 static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
                                       unsigned long offset, u16 *buf,
                                       int len)
 {
-       unsigned long fifoaddr = r8a66597->reg + offset;
+       void __iomem *fifoaddr = r8a66597->reg + offset;
        unsigned long count;
        unsigned char *pb;
        int i;
 
        if (r8a66597->pdata->on_chip) {
                count = len / 4;
-               outsl(fifoaddr, buf, count);
+               iowrite32_rep(fifoaddr, buf, count);
 
                if (len & 0x00000003) {
                        pb = (unsigned char *)buf + count * 4;
                        for (i = 0; i < (len & 0x00000003); i++) {
                                if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
-                                       outb(pb[i], fifoaddr + i);
+                                       iowrite8(pb[i], fifoaddr + i);
                                else
-                                       outb(pb[i], fifoaddr + 3 - i);
+                                       iowrite8(pb[i], fifoaddr + 3 - i);
                        }
                }
        } else {
                int odd = len & 0x0001;
 
                len = len / 2;
-               outsw(fifoaddr, buf, len);
+               ioread16_rep(fifoaddr, buf, len);
                if (unlikely(odd)) {
                        buf = &buf[len];
-                       outb((unsigned char)*buf, fifoaddr);
+                       iowrite8((unsigned char)*buf, fifoaddr);
                }
        }
 }
index edffd81fc253f390e8bf3b42e1fab702bb2baae1..11482b6b938152bcb4ff1b752f031dce1cc71ba3 100644 (file)
@@ -78,6 +78,8 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
                        xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
                                        " endpoint cmd after reset endpoint\n");
        }
+       if (pdev->vendor == PCI_VENDOR_ID_NEC)
+               xhci->quirks |= XHCI_NEC_HOST;
 
        /* Make sure the HC is halted. */
        retval = xhci_halt(xhci);
index 36c858e5b529136d8ec76af58454f466a10de793..94e6934edb09c0e3a06dd696a96c3d825719ede6 100644 (file)
@@ -182,8 +182,12 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
  * set, but other sections talk about dealing with the chain bit set.  This was
  * fixed in the 0.96 specification errata, but we have to assume that all 0.95
  * xHCI hardware can't handle the chain bit being cleared on a link TRB.
+ *
+ * @more_trbs_coming:  Will you enqueue more TRBs before calling
+ *                     prepare_transfer()?
  */
-static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
+static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
+               bool consumer, bool more_trbs_coming)
 {
        u32 chain;
        union xhci_trb *next;
@@ -199,15 +203,28 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
        while (last_trb(xhci, ring, ring->enq_seg, next)) {
                if (!consumer) {
                        if (ring != xhci->event_ring) {
-                               if (chain) {
-                                       next->link.control |= TRB_CHAIN;
-
-                                       /* Give this link TRB to the hardware */
-                                       wmb();
-                                       next->link.control ^= TRB_CYCLE;
-                               } else {
+                               /*
+                                * If the caller doesn't plan on enqueueing more
+                                * TDs before ringing the doorbell, then we
+                                * don't want to give the link TRB to the
+                                * hardware just yet.  We'll give the link TRB
+                                * back in prepare_ring() just before we enqueue
+                                * the TD at the top of the ring.
+                                */
+                               if (!chain && !more_trbs_coming)
                                        break;
+
+                               /* If we're not dealing with 0.95 hardware,
+                                * carry over the chain bit of the previous TRB
+                                * (which may mean the chain bit is cleared).
+                                */
+                               if (!xhci_link_trb_quirk(xhci)) {
+                                       next->link.control &= ~TRB_CHAIN;
+                                       next->link.control |= chain;
                                }
+                               /* Give this link TRB to the hardware */
+                               wmb();
+                               next->link.control ^= TRB_CYCLE;
                        }
                        /* Toggle the cycle bit after the last ring segment. */
                        if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
@@ -1071,6 +1088,15 @@ bandwidth_change:
                        xhci_warn(xhci, "Reset device command completion "
                                        "for disabled slot %u\n", slot_id);
                break;
+       case TRB_TYPE(TRB_NEC_GET_FW):
+               if (!(xhci->quirks & XHCI_NEC_HOST)) {
+                       xhci->error_bitmask |= 1 << 6;
+                       break;
+               }
+               xhci_dbg(xhci, "NEC firmware version %2x.%02x\n",
+                               NEC_FW_MAJOR(event->status),
+                               NEC_FW_MINOR(event->status));
+               break;
        default:
                /* Skip over unknown commands on the event ring */
                xhci->error_bitmask |= 1 << 6;
@@ -1079,6 +1105,17 @@ bandwidth_change:
        inc_deq(xhci, xhci->cmd_ring, false);
 }
 
+static void handle_vendor_event(struct xhci_hcd *xhci,
+               union xhci_trb *event)
+{
+       u32 trb_type;
+
+       trb_type = TRB_FIELD_TO_TYPE(event->generic.field[3]);
+       xhci_dbg(xhci, "Vendor specific event TRB type = %u\n", trb_type);
+       if (trb_type == TRB_NEC_CMD_COMP && (xhci->quirks & XHCI_NEC_HOST))
+               handle_cmd_completion(xhci, &event->event_cmd);
+}
+
 static void handle_port_status(struct xhci_hcd *xhci,
                union xhci_trb *event)
 {
@@ -1659,7 +1696,10 @@ void xhci_handle_event(struct xhci_hcd *xhci)
                        update_ptrs = 0;
                break;
        default:
-               xhci->error_bitmask |= 1 << 3;
+               if ((event->event_cmd.flags & TRB_TYPE_BITMASK) >= TRB_TYPE(48))
+                       handle_vendor_event(xhci, event);
+               else
+                       xhci->error_bitmask |= 1 << 3;
        }
        /* Any of the above functions may drop and re-acquire the lock, so check
         * to make sure a watchdog timer didn't mark the host as non-responsive.
@@ -1684,9 +1724,12 @@ void xhci_handle_event(struct xhci_hcd *xhci)
 /*
  * Generic function for queueing a TRB on a ring.
  * The caller must have checked to make sure there's room on the ring.
+ *
+ * @more_trbs_coming:  Will you enqueue more TRBs before calling
+ *                     prepare_transfer()?
  */
 static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
-               bool consumer,
+               bool consumer, bool more_trbs_coming,
                u32 field1, u32 field2, u32 field3, u32 field4)
 {
        struct xhci_generic_trb *trb;
@@ -1696,7 +1739,7 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
        trb->field[1] = field2;
        trb->field[2] = field3;
        trb->field[3] = field4;
-       inc_enq(xhci, ring, consumer);
+       inc_enq(xhci, ring, consumer, more_trbs_coming);
 }
 
 /*
@@ -1965,6 +2008,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        int trb_buff_len, this_sg_len, running_total;
        bool first_trb;
        u64 addr;
+       bool more_trbs_coming;
 
        struct xhci_generic_trb *start_trb;
        int start_cycle;
@@ -2050,7 +2094,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                length_field = TRB_LEN(trb_buff_len) |
                        remainder |
                        TRB_INTR_TARGET(0);
-               queue_trb(xhci, ep_ring, false,
+               if (num_trbs > 1)
+                       more_trbs_coming = true;
+               else
+                       more_trbs_coming = false;
+               queue_trb(xhci, ep_ring, false, more_trbs_coming,
                                lower_32_bits(addr),
                                upper_32_bits(addr),
                                length_field,
@@ -2101,6 +2149,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        int num_trbs;
        struct xhci_generic_trb *start_trb;
        bool first_trb;
+       bool more_trbs_coming;
        int start_cycle;
        u32 field, length_field;
 
@@ -2189,7 +2238,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                length_field = TRB_LEN(trb_buff_len) |
                        remainder |
                        TRB_INTR_TARGET(0);
-               queue_trb(xhci, ep_ring, false,
+               if (num_trbs > 1)
+                       more_trbs_coming = true;
+               else
+                       more_trbs_coming = false;
+               queue_trb(xhci, ep_ring, false, more_trbs_coming,
                                lower_32_bits(addr),
                                upper_32_bits(addr),
                                length_field,
@@ -2268,7 +2321,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        /* Queue setup TRB - see section 6.4.1.2.1 */
        /* FIXME better way to translate setup_packet into two u32 fields? */
        setup = (struct usb_ctrlrequest *) urb->setup_packet;
-       queue_trb(xhci, ep_ring, false,
+       queue_trb(xhci, ep_ring, false, true,
                        /* FIXME endianness is probably going to bite my ass here. */
                        setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16,
                        setup->wIndex | setup->wLength << 16,
@@ -2284,7 +2337,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        if (urb->transfer_buffer_length > 0) {
                if (setup->bRequestType & USB_DIR_IN)
                        field |= TRB_DIR_IN;
-               queue_trb(xhci, ep_ring, false,
+               queue_trb(xhci, ep_ring, false, true,
                                lower_32_bits(urb->transfer_dma),
                                upper_32_bits(urb->transfer_dma),
                                length_field,
@@ -2301,7 +2354,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                field = 0;
        else
                field = TRB_DIR_IN;
-       queue_trb(xhci, ep_ring, false,
+       queue_trb(xhci, ep_ring, false, false,
                        0,
                        0,
                        TRB_INTR_TARGET(0),
@@ -2338,7 +2391,7 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
                                        "unfailable commands failed.\n");
                return -ENOMEM;
        }
-       queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
+       queue_trb(xhci, xhci->cmd_ring, false, false, field1, field2, field3,
                        field4 | xhci->cmd_ring->cycle_state);
        return 0;
 }
@@ -2378,6 +2431,12 @@ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
                        false);
 }
 
+int xhci_queue_vendor_command(struct xhci_hcd *xhci,
+               u32 field1, u32 field2, u32 field3, u32 field4)
+{
+       return queue_command(xhci, field1, field2, field3, field4, false);
+}
+
 /* Queue a reset device command TRB */
 int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id)
 {
index 40e0a0c221b82cddfbcb6875f87cdaafcf390c16..27345cd04da0ccf99335064e2f37ad0950fb511f 100644 (file)
@@ -105,6 +105,33 @@ int xhci_halt(struct xhci_hcd *xhci)
                        STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
 }
 
+/*
+ * Set the run bit and wait for the host to be running.
+ */
+int xhci_start(struct xhci_hcd *xhci)
+{
+       u32 temp;
+       int ret;
+
+       temp = xhci_readl(xhci, &xhci->op_regs->command);
+       temp |= (CMD_RUN);
+       xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
+                       temp);
+       xhci_writel(xhci, temp, &xhci->op_regs->command);
+
+       /*
+        * Wait for the HCHalted Status bit to be 0 to indicate the host is
+        * running.
+        */
+       ret = handshake(xhci, &xhci->op_regs->status,
+                       STS_HALT, 0, XHCI_MAX_HALT_USEC);
+       if (ret == -ETIMEDOUT)
+               xhci_err(xhci, "Host took too long to start, "
+                               "waited %u microseconds.\n",
+                               XHCI_MAX_HALT_USEC);
+       return ret;
+}
+
 /*
  * Reset a halted HC, and set the internal HC state to HC_STATE_HALT.
  *
@@ -116,6 +143,7 @@ int xhci_reset(struct xhci_hcd *xhci)
 {
        u32 command;
        u32 state;
+       int ret;
 
        state = xhci_readl(xhci, &xhci->op_regs->status);
        if ((state & STS_HALT) == 0) {
@@ -130,7 +158,17 @@ int xhci_reset(struct xhci_hcd *xhci)
        /* XXX: Why does EHCI set this here?  Shouldn't other code do this? */
        xhci_to_hcd(xhci)->state = HC_STATE_HALT;
 
-       return handshake(xhci, &xhci->op_regs->command, CMD_RESET, 0, 250 * 1000);
+       ret = handshake(xhci, &xhci->op_regs->command,
+                       CMD_RESET, 0, 250 * 1000);
+       if (ret)
+               return ret;
+
+       xhci_dbg(xhci, "Wait for controller to be ready for doorbell rings\n");
+       /*
+        * 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);
 }
 
 
@@ -448,17 +486,20 @@ int xhci_run(struct usb_hcd *hcd)
 
        if (NUM_TEST_NOOPS > 0)
                doorbell = xhci_setup_one_noop(xhci);
+       if (xhci->quirks & XHCI_NEC_HOST)
+               xhci_queue_vendor_command(xhci, 0, 0, 0,
+                               TRB_TYPE(TRB_NEC_GET_FW));
+
+       if (xhci_start(xhci)) {
+               xhci_halt(xhci);
+               return -ENODEV;
+       }
 
-       temp = xhci_readl(xhci, &xhci->op_regs->command);
-       temp |= (CMD_RUN);
-       xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
-                       temp);
-       xhci_writel(xhci, temp, &xhci->op_regs->command);
-       /* Flush PCI posted writes */
-       temp = xhci_readl(xhci, &xhci->op_regs->command);
        xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp);
        if (doorbell)
                (*doorbell)(xhci);
+       if (xhci->quirks & XHCI_NEC_HOST)
+               xhci_ring_cmd_db(xhci);
 
        xhci_dbg(xhci, "Finished xhci_run\n");
        return 0;
index dada2fb592616f770c0c01845438a07257d6cf7b..8b4b7d39f79cafb927523e94d95a93f59dd1b9cf 100644 (file)
@@ -925,6 +925,7 @@ union xhci_trb {
 /* TRB bit mask */
 #define        TRB_TYPE_BITMASK        (0xfc00)
 #define TRB_TYPE(p)            ((p) << 10)
+#define TRB_FIELD_TO_TYPE(p)   (((p) & TRB_TYPE_BITMASK) >> 10)
 /* TRB type IDs */
 /* bulk, interrupt, isoc scatter/gather, and control data stage */
 #define TRB_NORMAL             1
@@ -992,6 +993,14 @@ union xhci_trb {
 #define TRB_MFINDEX_WRAP       39
 /* TRB IDs 40-47 reserved, 48-63 is vendor-defined */
 
+/* Nec vendor-specific command completion event. */
+#define        TRB_NEC_CMD_COMP        48
+/* Get NEC firmware revision. */
+#define        TRB_NEC_GET_FW          49
+
+#define NEC_FW_MINOR(p)                (((p) >> 0) & 0xff)
+#define NEC_FW_MAJOR(p)                (((p) >> 8) & 0xff)
+
 /*
  * TRBS_PER_SEGMENT must be a multiple of 4,
  * since the command ring is 64-byte aligned.
@@ -1172,6 +1181,7 @@ struct xhci_hcd {
        unsigned int            quirks;
 #define        XHCI_LINK_TRB_QUIRK     (1 << 0)
 #define XHCI_RESET_EP_QUIRK    (1 << 1)
+#define XHCI_NEC_HOST          (1 << 2)
 };
 
 /* For testing purposes */
@@ -1379,6 +1389,8 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci);
 int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id);
 int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
                u32 slot_id);
+int xhci_queue_vendor_command(struct xhci_hcd *xhci,
+               u32 field1, u32 field2, u32 field3, u32 field4);
 int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
                unsigned int ep_index);
 int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
index fad70bc835558a501e0f06a615237e07be4197e0..3b795c56221f8c30f757fe9420eea7424dc2d804 100644 (file)
@@ -219,8 +219,8 @@ static int musb_ulpi_write(struct otg_transceiver *otg,
        return 0;
 }
 #else
-#define musb_ulpi_read(a, b)           NULL
-#define musb_ulpi_write(a, b, c)       NULL
+#define musb_ulpi_read         NULL
+#define musb_ulpi_write                NULL
 #endif
 
 static struct otg_io_access_ops musb_ulpi_access = {
@@ -451,10 +451,6 @@ void musb_hnp_stop(struct musb *musb)
  * @param power
  */
 
-#define STAGE0_MASK (MUSB_INTR_RESUME | MUSB_INTR_SESSREQ \
-               | MUSB_INTR_VBUSERROR | MUSB_INTR_CONNECT \
-               | MUSB_INTR_RESET)
-
 static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                                u8 devctl, u8 power)
 {
@@ -642,7 +638,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                handled = IRQ_HANDLED;
        }
 
-
+#endif
        if (int_usb & MUSB_INTR_SUSPEND) {
                DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",
                                otg_state_string(musb), devctl, power);
@@ -705,6 +701,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                }
        }
 
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
        if (int_usb & MUSB_INTR_CONNECT) {
                struct usb_hcd *hcd = musb_to_hcd(musb);
                void __iomem *mbase = musb->mregs;
@@ -1597,7 +1594,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
        /* the core can interrupt us for multiple reasons; docs have
         * a generic interrupt flowchart to follow
         */
-       if (musb->int_usb & STAGE0_MASK)
+       if (musb->int_usb)
                retval |= musb_stage0_irq(musb, musb->int_usb,
                                devctl, power);
 
index b22d02dea7d361698e830efa3919df3802a5b3b4..91d67794e3503eeeb982c8c85e537e48c7d15394 100644 (file)
@@ -470,7 +470,8 @@ struct musb_csr_regs {
 
 struct musb_context_registers {
 
-#ifdef CONFIG_PM
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+    defined(CONFIG_ARCH_OMAP4)
        u32 otg_sysconfig, otg_forcestandby;
 #endif
        u8 power;
@@ -484,7 +485,8 @@ struct musb_context_registers {
        struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
 };
 
-#ifdef CONFIG_PM
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+    defined(CONFIG_ARCH_OMAP4)
 extern void musb_platform_save_context(struct musb *musb,
                struct musb_context_registers *musb_context);
 extern void musb_platform_restore_context(struct musb *musb,
index 1008044a3bbc38efc580ae72211fd7a33b29d4d3..dc66e4376d4906a4454b90a393851cd72631aefa 100644 (file)
@@ -132,18 +132,9 @@ static void configure_channel(struct dma_channel *channel,
        if (mode) {
                csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;
                BUG_ON(len < packet_sz);
-
-               if (packet_sz >= 64) {
-                       csr |= MUSB_HSDMA_BURSTMODE_INCR16
-                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
-               } else if (packet_sz >= 32) {
-                       csr |= MUSB_HSDMA_BURSTMODE_INCR8
-                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
-               } else if (packet_sz >= 16) {
-                       csr |= MUSB_HSDMA_BURSTMODE_INCR4
-                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
-               }
        }
+       csr |= MUSB_HSDMA_BURSTMODE_INCR16
+                               << MUSB_HSDMA_BURSTMODE_SHIFT;
 
        csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
                | (1 << MUSB_HSDMA_ENABLE_SHIFT)
index b1b346932946d447dcf11b1ddcb952edd49acaab..d331b222ad214cdd43e815761eb08a3c300e8196 100644 (file)
@@ -59,12 +59,17 @@ static int ulpi_set_flags(struct otg_transceiver *otg)
 
 static int ulpi_init(struct otg_transceiver *otg)
 {
-       int i, vid, pid;
-
-       vid = (otg_io_read(otg, ULPI_VENDOR_ID_HIGH) << 8) |
-              otg_io_read(otg, ULPI_VENDOR_ID_LOW);
-       pid = (otg_io_read(otg, ULPI_PRODUCT_ID_HIGH) << 8) |
-              otg_io_read(otg, ULPI_PRODUCT_ID_LOW);
+       int i, vid, pid, ret;
+       u32 ulpi_id = 0;
+
+       for (i = 0; i < 4; i++) {
+               ret = otg_io_read(otg, ULPI_PRODUCT_ID_HIGH - i);
+               if (ret < 0)
+                       return ret;
+               ulpi_id = (ulpi_id << 8) | ret;
+       }
+       vid = ulpi_id & 0xffff;
+       pid = ulpi_id >> 16;
 
        pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
 
index 3edda3ed822a5326e1072e3f49bc163af2878dae..fd35f73b572154b33b60d6415cf59ea4edde054f 100644 (file)
@@ -1239,8 +1239,7 @@ static void digi_write_bulk_callback(struct urb *urb)
 
        /* port and serial sanity check */
        if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
-               dev_err(&port->dev,
-                       "%s: port or port->private is NULL, status=%d\n",
+               pr_err("%s: port or port->private is NULL, status=%d\n",
                        __func__, status);
                return;
        }
index 050211afc07ede3ded137a28b46aba79dcb01ebe..da7e334b0407a3ef0e210a56dcc02ea3f2a14db8 100644 (file)
@@ -653,7 +653,6 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
        { USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
        { USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
-       { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
@@ -2005,6 +2004,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
                                "urb failed to set to rts/cts flow control\n");
                }
 
+               /* raise DTR/RTS */
+               set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
        } else {
                /*
                 * Xon/Xoff code
@@ -2052,6 +2053,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
                        }
                }
 
+               /* lower DTR/RTS */
+               clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
        }
        return;
 }
index 94d86c3febcb8e0ad67ba11b105822e8d25ba17a..bbc159a1df45d330f926a6e003dadece3c1b4daa 100644 (file)
 #define CONTEC_VID             0x06CE  /* Vendor ID */
 #define CONTEC_COM1USBH_PID    0x8311  /* COM-1(USB)H */
 
-/*
- * Contec products (http://www.contec.com)
- * Submitted by Daniel Sangorrin
- */
-#define CONTEC_VID             0x06CE  /* Vendor ID */
-#define CONTEC_COM1USBH_PID    0x8311  /* COM-1(USB)H */
-
 /*
  * Definitions for B&B Electronics products.
  */
index f8424d1bfc1b279a5e4a51fc4453fb3e3f847ffb..585b7e6637405981e5019790bbdb0700109f87d0 100644 (file)
@@ -730,7 +730,6 @@ static void mos7840_bulk_in_callback(struct urb *urb)
        mos7840_port = urb->context;
        if (!mos7840_port) {
                dbg("%s", "NULL mos7840_port pointer");
-               mos7840_port->read_urb_busy = false;
                return;
        }
 
index 04bb759536bb81f6e41ecc2b4537e5e2e0b2790f..93d72eb8cafc8deaa36a52e2632a6cee3429ce66 100644 (file)
@@ -139,6 +139,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                                        "Could not set interface, error %d\n",
                                        retval);
                                retval = -ENODEV;
+                               kfree(data);
                        }
                        return retval;
                }
@@ -155,6 +156,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                                        "Could not set interface, error %d\n",
                                        retval);
                                retval = -ENODEV;
+                               kfree(data);
                        }
                        return retval;
                }
@@ -163,6 +165,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
        default:
                dev_err(&serial->dev->dev,
                        "unknown number of interfaces: %d\n", nintf);
+               kfree(data);
                return -ENODEV;
        }
 
index 0f41c9195e9bb9942adc2e6e15a43af4a34393e2..df5b6b971f2633954c3233ead3bb1b648532c507 100644 (file)
@@ -637,7 +637,7 @@ const static struct file_operations vhost_net_fops = {
 };
 
 static struct miscdevice vhost_net_misc = {
-       VHOST_NET_MINOR,
+       MISC_DYNAMIC_MINOR,
        "vhost-net",
        &vhost_net_fops,
 };
index 1e6fec487973c45a0407326f09a62f6015c39589..3d94a1471724ff620ba580808be1ceec0d868b15 100644 (file)
@@ -8,6 +8,9 @@ menu "Graphics support"
 config HAVE_FB_ATMEL
        bool
 
+config HAVE_FB_IMX
+       bool
+
 source "drivers/char/agp/Kconfig"
 
 source "drivers/gpu/vga/Kconfig"
@@ -400,9 +403,6 @@ config FB_SA1100
          If you plan to use the LCD display with your SA-1100 system, say
          Y here.
 
-config HAVE_FB_IMX
-       bool
-
 config FB_IMX
        tristate "Motorola i.MX LCD support"
        depends on FB && (HAVE_FB_IMX || ARCH_MX1 || ARCH_MX2)
index 51fcc0a2c94a9097aea33eff174b1b38969b263d..e45833ce975bd6cb60fb2d8b09db767d28987c14 100644 (file)
@@ -242,7 +242,7 @@ void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
-       u32 color = rect->color, dx = rect->dx, width = rect->width, rotation = 0;
+       u32 color, dx = rect->dx, width = rect->width, rotation = 0;
 
        if (par->asleep)
                return;
@@ -253,8 +253,11 @@ void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
                return;
        }
 
-       color |= (rect->color << 8);
-       color |= (rect->color << 16);
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+           info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+               color = ((u32 *)(info->pseudo_palette))[rect->color];
+       else
+               color = rect->color;
 
        if (info->var.bits_per_pixel == 24) {
                /* In 24 bpp, the engine is in 8 bpp - this requires that all */
index 921ca37398f39b63943f3484192140dc355087d6..3ec24609151e8ec322c48afcebae8dc9ce578b5d 100644 (file)
@@ -756,7 +756,6 @@ out:
 out1:
        backlight_device_unregister(bl);
 out2:
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 
        return ret;
@@ -776,7 +775,6 @@ static int __devexit adp8860_remove(struct i2c_client *client)
                        &adp8860_bl_attr_group);
 
        backlight_device_unregister(data->bl);
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 
        return 0;
index e03e60bbfd855f01301ab14d71b1fc9d94453bcc..2a04b382ec4834a03270db15701136f5f01694cf 100644 (file)
@@ -119,7 +119,6 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
 
 err_reg:
        data->bl = NULL;
-       i2c_set_clientdata(client, NULL);
 err_gpio_dir:
        gpio_free(TOSA_GPIO_BL_C20MA);
 err_gpio_bl:
@@ -133,7 +132,6 @@ static int __devexit tosa_bl_remove(struct i2c_client *client)
 
        backlight_device_unregister(data->bl);
        data->bl = NULL;
-       i2c_set_clientdata(client, NULL);
 
        gpio_free(TOSA_GPIO_BL_C20MA);
 
index 2c371c07f0daaff562b844184bfb742284b9cc53..09f1b9b462f4a8a4ce86a600aa55a4cbf1685622 100644 (file)
@@ -275,7 +275,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par,
 
 static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct bw2_par *par;
        int linebytes, err;
index d12e05b6e63f96ce0cd36ba1ddb810167953d280..e5dc2241194fed66606c1e694aa4c77ed3357c81 100644 (file)
@@ -465,7 +465,7 @@ static void cg14_unmap_regs(struct of_device *op, struct fb_info *info,
 
 static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct cg14_par *par;
        int is_8mb, linebytes, i, err;
index b98f93f7f6638f0a02a39250aaeaca54b595bbb3..558d73a948a0d836c73ea20c26440229738ba581 100644 (file)
@@ -349,7 +349,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par)
 static int __devinit cg3_probe(struct of_device *op,
                               const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct cg3_par *par;
        int linebytes, err;
index 073c9b408cf7ce1ceff2b5eb52c6f49510273291..6b93ef93cb12c08179c973e31bf97ff27eb4d56b 100644 (file)
@@ -100,6 +100,16 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma,
        /* protect against the workqueue changing the page list */
        mutex_lock(&fbdefio->lock);
 
+       /*
+        * We want the page to remain locked from ->page_mkwrite until
+        * the PTE is marked dirty to avoid page_mkclean() being called
+        * before the PTE is updated, which would leave the page ignored
+        * by defio.
+        * Do this by locking the page here and informing the caller
+        * about it with VM_FAULT_LOCKED.
+        */
+       lock_page(page);
+
        /* we loop through the pagelist before adding in order
        to keep the pagelist sorted */
        list_for_each_entry(cur, &fbdefio->pagelist, lru) {
@@ -121,7 +131,7 @@ page_already_added:
 
        /* come back after delay to process the deferred IO */
        schedule_delayed_work(&info->deferred_work, fbdefio->delay);
-       return 0;
+       return VM_FAULT_LOCKED;
 }
 
 static const struct vm_operations_struct fb_deferred_io_vm_ops = {
@@ -155,41 +165,25 @@ static void fb_deferred_io_work(struct work_struct *work)
 {
        struct fb_info *info = container_of(work, struct fb_info,
                                                deferred_work.work);
+       struct list_head *node, *next;
+       struct page *cur;
        struct fb_deferred_io *fbdefio = info->fbdefio;
-       struct page *page, *tmp_page;
-       struct list_head *node, *tmp_node;
-       struct list_head non_dirty;
-
-       INIT_LIST_HEAD(&non_dirty);
 
        /* here we mkclean the pages, then do all deferred IO */
        mutex_lock(&fbdefio->lock);
-       list_for_each_entry_safe(page, tmp_page, &fbdefio->pagelist, lru) {
-               lock_page(page);
-               /*
-                * The workqueue callback can be triggered after a
-                * ->page_mkwrite() call but before the PTE has been marked
-                * dirty. In this case page_mkclean() won't "rearm" the page.
-                *
-                * To avoid this, remove those "non-dirty" pages from the
-                * pagelist before calling the driver's callback, then add
-                * them back to get processed on the next work iteration.
-                * At that time, their PTEs will hopefully be dirty for real.
-                */
-               if (!page_mkclean(page))
-                       list_move_tail(&page->lru, &non_dirty);
-               unlock_page(page);
+       list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+               lock_page(cur);
+               page_mkclean(cur);
+               unlock_page(cur);
        }
 
        /* driver's callback with pagelist */
        fbdefio->deferred_io(info, &fbdefio->pagelist);
 
-       /* clear the list... */
-       list_for_each_safe(node, tmp_node, &fbdefio->pagelist) {
+       /* clear the list */
+       list_for_each_safe(node, next, &fbdefio->pagelist) {
                list_del(node);
        }
-       /* ... and add back the "non-dirty" pages to the list */
-       list_splice_tail(&non_dirty, &fbdefio->pagelist);
        mutex_unlock(&fbdefio->lock);
 }
 
@@ -218,7 +212,6 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_open);
 void fb_deferred_io_cleanup(struct fb_info *info)
 {
        struct fb_deferred_io *fbdefio = info->fbdefio;
-       struct list_head *node, *tmp_node;
        struct page *page;
        int i;
 
@@ -226,13 +219,6 @@ void fb_deferred_io_cleanup(struct fb_info *info)
        cancel_delayed_work(&info->deferred_work);
        flush_scheduled_work();
 
-       /*  the list may have still some non-dirty pages at this point */
-       mutex_lock(&fbdefio->lock);
-       list_for_each_safe(node, tmp_node, &fbdefio->pagelist) {
-               list_del(node);
-       }
-       mutex_unlock(&fbdefio->lock);
-
        /* clear out the mapping that we setup */
        for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
                page = fb_deferred_io_page(info, i);
index 76e7dac6f25901843da1717d6fb55a3c721a8e16..70b1d9d51c9601e2c4c338f58d29f7d4f59214dd 100644 (file)
@@ -40,7 +40,7 @@ static int vram;
 static int vt_switch;
 
 /* Modes relevant to the GX (taken from modedb.c) */
-static struct fb_videomode gx_modedb[] __initdata = {
+static struct fb_videomode gx_modedb[] __devinitdata = {
        /* 640x480-60 VESA */
        { NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
          0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
@@ -110,14 +110,15 @@ static struct fb_videomode gx_modedb[] __initdata = {
 #ifdef CONFIG_OLPC
 #include <asm/olpc.h>
 
-static struct fb_videomode gx_dcon_modedb[] __initdata = {
+static struct fb_videomode gx_dcon_modedb[] __devinitdata = {
        /* The only mode the DCON has is 1200x900 */
        { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
          FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
          FB_VMODE_NONINTERLACED, 0 }
 };
 
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+               unsigned int *size)
 {
        if (olpc_has_dcon()) {
                *modedb = (struct fb_videomode *) gx_dcon_modedb;
@@ -129,7 +130,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
 }
 
 #else
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+               unsigned int *size)
 {
        *modedb = (struct fb_videomode *) gx_modedb;
        *size = ARRAY_SIZE(gx_modedb);
@@ -226,7 +228,8 @@ static int gxfb_blank(int blank_mode, struct fb_info *info)
        return gx_blank_display(info, blank_mode);
 }
 
-static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+static int __devinit gxfb_map_video_memory(struct fb_info *info,
+               struct pci_dev *dev)
 {
        struct gxfb_par *par = info->par;
        int ret;
@@ -290,7 +293,7 @@ static struct fb_ops gxfb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
+static struct fb_info *__devinit gxfb_init_fbinfo(struct device *dev)
 {
        struct gxfb_par *par;
        struct fb_info *info;
@@ -371,7 +374,8 @@ static int gxfb_resume(struct pci_dev *pdev)
 }
 #endif
 
-static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit gxfb_probe(struct pci_dev *pdev,
+               const struct pci_device_id *id)
 {
        struct gxfb_par *par;
        struct fb_info *info;
@@ -451,7 +455,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
        return ret;
 }
 
-static void gxfb_remove(struct pci_dev *pdev)
+static void __devexit gxfb_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct gxfb_par *par = info->par;
index 1a18da86d3fa3cbde2b899831ec136a178527340..39bdbedf43b481253e7eb3586d15050c83abb94c 100644 (file)
@@ -35,7 +35,7 @@ static int vt_switch;
  * we try to make it something sane - 640x480-60 is sane
  */
 
-static struct fb_videomode geode_modedb[] __initdata = {
+static struct fb_videomode geode_modedb[] __devinitdata = {
        /* 640x480-60 */
        { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
          FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
@@ -219,14 +219,15 @@ static struct fb_videomode geode_modedb[] __initdata = {
 #ifdef CONFIG_OLPC
 #include <asm/olpc.h>
 
-static struct fb_videomode olpc_dcon_modedb[] __initdata = {
+static struct fb_videomode olpc_dcon_modedb[] __devinitdata = {
        /* The only mode the DCON has is 1200x900 */
        { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
          FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
          FB_VMODE_NONINTERLACED, 0 }
 };
 
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+               unsigned int *size)
 {
        if (olpc_has_dcon()) {
                *modedb = (struct fb_videomode *) olpc_dcon_modedb;
@@ -238,7 +239,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
 }
 
 #else
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+               unsigned int *size)
 {
        *modedb = (struct fb_videomode *) geode_modedb;
        *size = ARRAY_SIZE(geode_modedb);
@@ -334,7 +336,7 @@ static int lxfb_blank(int blank_mode, struct fb_info *info)
 }
 
 
-static int __init lxfb_map_video_memory(struct fb_info *info,
+static int __devinit lxfb_map_video_memory(struct fb_info *info,
                                        struct pci_dev *dev)
 {
        struct lxfb_par *par = info->par;
@@ -412,7 +414,7 @@ static struct fb_ops lxfb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
+static struct fb_info * __devinit lxfb_init_fbinfo(struct device *dev)
 {
        struct lxfb_par *par;
        struct fb_info *info;
@@ -496,7 +498,7 @@ static int lxfb_resume(struct pci_dev *pdev)
 #define lxfb_resume NULL
 #endif
 
-static int __init lxfb_probe(struct pci_dev *pdev,
+static int __devinit lxfb_probe(struct pci_dev *pdev,
                             const struct pci_device_id *id)
 {
        struct lxfb_par *par;
@@ -588,7 +590,7 @@ err:
        return ret;
 }
 
-static void lxfb_remove(struct pci_dev *pdev)
+static void __devexit lxfb_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct lxfb_par *par = info->par;
index 3d7895316eaf37e79bb56f2413d748fcbdfca131..9e8bf7d5e249df2a3d0f3243181bab0b76b633a9 100644 (file)
@@ -550,7 +550,7 @@ static void leo_unmap_regs(struct of_device *op, struct fb_info *info,
 static int __devinit leo_probe(struct of_device *op,
                               const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct leo_par *par;
        int linebytes, err;
index 0540de4f5cb48f062bedb6d9874964ab1423d62b..4e2b8cc3d46093299a2ae05178ead6db2e783640 100644 (file)
@@ -553,7 +553,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par)
 static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev,
                                               const struct of_device_id *id)
 {
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct device *dev = &ofdev->dev;
        struct mb862xxfb_par *par;
        struct fb_info *info;
index d4cde79ea15e61362a34736179520053d68383bc..81687ed26ba9ed55d761b550d1df59b59ce371a9 100644 (file)
@@ -596,8 +596,6 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev)
                goto release_regs;
        }
 
-       nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2);
-
        fbi->clk = clk_get(&pdev->dev, NULL);
        if (!fbi->clk || IS_ERR(fbi->clk)) {
                printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n");
index 43ab7d8b66b2bf9e32d2e687747a8e6427daa6d5..7767338f8b14028fe4ff409eed4717e99296f0ba 100644 (file)
@@ -572,22 +572,12 @@ static enum omapfb_update_mode omap_lcdc_get_update_mode(void)
 /* PM code called only in internal controller mode */
 static void omap_lcdc_suspend(void)
 {
-       if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
-               disable_controller();
-               omap_stop_lcd_dma();
-       }
+       omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED);
 }
 
 static void omap_lcdc_resume(void)
 {
-       if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
-               setup_regs();
-               load_palette();
-               setup_lcd_dma();
-               set_load_mode(OMAP_LCDC_LOAD_FRAME);
-               enable_irqs(OMAP_LCDC_IRQ_DONE);
-               enable_controller();
-       }
+       omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE);
 }
 
 static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps)
index 1162603c72e5ff8557ab25b2122c201078f76b47..eada9f12efc767908c1c17f401e1ca0b925a1d37 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 
 #include "omapfb.h"
 #include "dispc.h"
@@ -83,13 +84,13 @@ static inline u32 rfbi_read_reg(int idx)
 
 static int rfbi_get_clocks(void)
 {
-       rfbi.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick");
+       rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick");
        if (IS_ERR(rfbi.dss_ick)) {
                dev_err(rfbi.fbdev->dev, "can't get ick\n");
                return PTR_ERR(rfbi.dss_ick);
        }
 
-       rfbi.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck");
+       rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "dss1_fck");
        if (IS_ERR(rfbi.dss1_fck)) {
                dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");
                clk_put(rfbi.dss_ick);
index c85dd408a9b87369fffdce371fad0754f1100810..6552751e81aaa058a18af29ff8892d9abe1a54af 100644 (file)
@@ -251,7 +251,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no
 
 static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct p9100_par *par;
        int linebytes, err;
index e8c769944812e90a81b7d0cf8bdbe5d3f5525fc8..12c451a711e935d767d74677923b1202f0ed629f 100644 (file)
@@ -991,13 +991,13 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
                priv->ch[j].lcdc = priv;
                memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
 
-               error = sh_mobile_lcdc_check_interface(&priv->ch[i]);
+               error = sh_mobile_lcdc_check_interface(&priv->ch[j]);
                if (error) {
                        dev_err(&pdev->dev, "unsupported interface type\n");
                        goto err1;
                }
-               init_waitqueue_head(&priv->ch[i].frame_end_wait);
-               init_completion(&priv->ch[i].vsync_completion);
+               init_waitqueue_head(&priv->ch[j].frame_end_wait);
+               init_completion(&priv->ch[j].vsync_completion);
                priv->ch[j].pan_offset = 0;
 
                switch (pdata->ch[i].chan) {
index ef7a7bd8b503492fec8aa1f56ab678adfe2f06f0..cc039b33d2d8bd762a493bd650fceb1b0895a52f 100644 (file)
@@ -365,7 +365,7 @@ static void tcx_unmap_regs(struct of_device *op, struct fb_info *info,
 static int __devinit tcx_probe(struct of_device *op,
                               const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct tcx_par *par;
        int linebytes, i, err;
index 95896f38792765b2c415a2f63a1e4747d947f632..ef8d9d558fc734183dd82a172e49f9ee7a07b8ae 100644 (file)
@@ -636,6 +636,9 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
        INIT_LIST_HEAD(&vp_dev->virtqueues);
        spin_lock_init(&vp_dev->lock);
 
+       /* Disable MSI/MSIX to bring device to a known good state. */
+       pci_msi_off(pci_dev);
+
        /* enable the device */
        err = pci_enable_device(pci_dev);
        if (err)
index 1ca88908723badfcb3aa9d07463b8f2988c28981..afe7e21dd0ae8a7dce4db7ee1a480ce931c42247 100644 (file)
@@ -119,7 +119,7 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
 
        desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);
        if (!desc)
-               return vq->vring.num;
+               return -ENOMEM;
 
        /* Transfer entries from the sg list into the indirect page */
        for (i = 0; i < out; i++) {
index 1cddf92cb9a604f8afd43312af0b46ef4d145bd8..750bc5281d79d18ec7c3fca85e31254aae412251 100644 (file)
@@ -346,9 +346,13 @@ static int __init at32_wdt_probe(struct platform_device *pdev)
        } else {
                wdt->users = 0;
        }
-       wdt->miscdev.minor = WATCHDOG_MINOR;
-       wdt->miscdev.name = "watchdog";
-       wdt->miscdev.fops = &at32_wdt_fops;
+
+       wdt->miscdev.minor      = WATCHDOG_MINOR;
+       wdt->miscdev.name       = "watchdog";
+       wdt->miscdev.fops       = &at32_wdt_fops;
+       wdt->miscdev.parent     = &pdev->dev;
+
+       platform_set_drvdata(pdev, wdt);
 
        if (at32_wdt_settimeout(timeout)) {
                at32_wdt_settimeout(TIMEOUT_DEFAULT);
@@ -360,17 +364,17 @@ static int __init at32_wdt_probe(struct platform_device *pdev)
        ret = misc_register(&wdt->miscdev);
        if (ret) {
                dev_dbg(&pdev->dev, "failed to register wdt miscdev\n");
-               goto err_iounmap;
+               goto err_register;
        }
 
-       platform_set_drvdata(pdev, wdt);
-       wdt->miscdev.parent = &pdev->dev;
        dev_info(&pdev->dev,
                "AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n",
                wdt->regs, wdt->timeout, nowayout);
 
        return 0;
 
+err_register:
+       platform_set_drvdata(pdev, NULL);
 err_iounmap:
        iounmap(wdt->regs);
 err_free:
index ca0f4c6cf5ab98217f1b444a94611b0098781041..1df284f9c2a1b3fcd9e667b49915e4dbc21f5de3 100644 (file)
@@ -273,7 +273,7 @@ static int __devinit gef_wdt_probe(struct of_device *dev,
                bus_clk = freq;
 
        /* Map devices registers into memory */
-       gef_wdt_regs = of_iomap(dev->node, 0);
+       gef_wdt_regs = of_iomap(dev->dev.of_node, 0);
        if (gef_wdt_regs == NULL)
                return -ENOMEM;
 
index ea25885781bba0f6902e2d0de30a82f7f104ec8c..2ee7dac55a3c454fb010c662e8dc9d11a7199f7b 100644 (file)
@@ -330,7 +330,6 @@ static void imx2_wdt_shutdown(struct platform_device *pdev)
 }
 
 static struct platform_driver imx2_wdt_driver = {
-       .probe          = imx2_wdt_probe,
        .remove         = __exit_p(imx2_wdt_remove),
        .shutdown       = imx2_wdt_shutdown,
        .driver         = {
index 6622335773bbc53fd2f0c3aa90b986d6b2dca0ea..4cda64dd309c0367208358ef6eb41b73180969cc 100644 (file)
@@ -189,7 +189,7 @@ static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev,
                                       const struct of_device_id *match)
 {
        int ret;
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct mpc8xxx_wdt_type *wdt_type = match->data;
        u32 freq = fsl_get_sys_freq();
        bool enabled;
index 89dd7b03529520df645e719e73e3d2e5f96c8477..b68d928c8f90fcf259c141b22f4fb7fa84729f84 100644 (file)
@@ -284,7 +284,7 @@ static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
        struct wm8350 *wm8350 = platform_get_drvdata(pdev);
 
        if (!wm8350) {
-               dev_err(wm8350->dev, "No driver data supplied\n");
+               pr_err("No driver data supplied\n");
                return -ENODEV;
        }
 
index eab33f1dbdf7013f451af491b882973ea017f718..7b547f53f65ee9267f19dd493a6ab7321310ed4c 100644 (file)
@@ -499,7 +499,7 @@ int xenbus_printf(struct xenbus_transaction t,
 #define PRINTF_BUFFER_SIZE 4096
        char *printf_buffer;
 
-       printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
+       printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_NOIO | __GFP_HIGH);
        if (printf_buffer == NULL)
                return -ENOMEM;
 
index f4909951667554b6e4263ebebedc6d2513599d48..9fdc7fe3a7bc127da02963e76c3628221c334ed0 100644 (file)
@@ -91,9 +91,10 @@ static struct afs_server *afs_alloc_server(struct afs_cell *cell,
 
                memcpy(&server->addr, addr, sizeof(struct in_addr));
                server->addr.s_addr = addr->s_addr;
+               _leave(" = %p{%d}", server, atomic_read(&server->usage));
+       } else {
+               _leave(" = NULL [nomem]");
        }
-
-       _leave(" = %p{%d}", server, atomic_read(&server->usage));
        return server;
 }
 
index 2c5f9a0e5d72bb0357c45d5524186c14b3284bca..63039ed9576f75c396ed0dae71bec1e4abf53058 100644 (file)
@@ -990,10 +990,9 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
 
                /* clear any space allocated but not loaded */
                if (phdr->p_filesz < phdr->p_memsz) {
-                       ret = clear_user((void *) (seg->addr + phdr->p_filesz),
-                                        phdr->p_memsz - phdr->p_filesz);
-                       if (ret)
-                               return ret;
+                       if (clear_user((void *) (seg->addr + phdr->p_filesz),
+                                      phdr->p_memsz - phdr->p_filesz))
+                               return -EFAULT;
                }
 
                if (mm) {
@@ -1027,7 +1026,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
        struct elf32_fdpic_loadseg *seg;
        struct elf32_phdr *phdr;
        unsigned long load_addr, delta_vaddr;
-       int loop, dvset, ret;
+       int loop, dvset;
 
        load_addr = params->load_addr;
        delta_vaddr = 0;
@@ -1127,9 +1126,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
                 * PT_LOAD */
                if (prot & PROT_WRITE && disp > 0) {
                        kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp);
-                       ret = clear_user((void __user *) maddr, disp);
-                       if (ret)
-                               return ret;
+                       if (clear_user((void __user *) maddr, disp))
+                               return -EFAULT;
                        maddr += disp;
                }
 
@@ -1164,19 +1162,17 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
                if (prot & PROT_WRITE && excess1 > 0) {
                        kdebug("clear[%d] ad=%lx sz=%lx",
                               loop, maddr + phdr->p_filesz, excess1);
-                       ret = clear_user((void __user *) maddr + phdr->p_filesz,
-                                        excess1);
-                       if (ret)
-                               return ret;
+                       if (clear_user((void __user *) maddr + phdr->p_filesz,
+                                      excess1))
+                               return -EFAULT;
                }
 
 #else
                if (excess > 0) {
                        kdebug("clear[%d] ad=%lx sz=%lx",
                               loop, maddr + phdr->p_filesz, excess);
-                       ret = clear_user((void *) maddr + phdr->p_filesz, excess);
-                       if (ret)
-                               return ret;
+                       if (clear_user((void *) maddr + phdr->p_filesz, excess))
+                               return -EFAULT;
                }
 #endif
 
index 49566c1687d84943d9187a12ff2d1490c8ec6ad2..811384bec8de8d486a9aa7355d49b0195995e97a 100644 (file)
 #endif
 
 /*
- * User data (stack, data section and bss) needs to be aligned
- * for the same reasons as SLAB memory is, and to the same amount.
- * Avoid duplicating architecture specific code by using the same
- * macro as with SLAB allocation:
+ * User data (data section and bss) needs to be aligned.
+ * We pick 0x20 here because it is the max value elf2flt has always
+ * used in producing FLAT files, and because it seems to be large
+ * enough to make all the gcc alignment related tests happy.
  */
-#ifdef ARCH_SLAB_MINALIGN
-#define FLAT_DATA_ALIGN        (ARCH_SLAB_MINALIGN)
-#else
-#define FLAT_DATA_ALIGN        (sizeof(void *))
-#endif
+#define FLAT_DATA_ALIGN        (0x20)
+
+/*
+ * User data (stack) also needs to be aligned.
+ * Here we can be a bit looser than the data sections since this
+ * needs to only meet arch ABI requirements.
+ */
+#define FLAT_STACK_ALIGN       max_t(unsigned long, sizeof(void *), ARCH_SLAB_MINALIGN)
 
 #define RELOC_FAILED 0xff00ff01                /* Relocation incorrect somewhere */
 #define UNLOADED_LIB 0x7ff000ff                /* Placeholder for unused library */
@@ -129,7 +132,7 @@ static unsigned long create_flat_tables(
 
        sp = (unsigned long *)p;
        sp -= (envc + argc + 2) + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
-       sp = (unsigned long *) ((unsigned long)sp & -FLAT_DATA_ALIGN);
+       sp = (unsigned long *) ((unsigned long)sp & -FLAT_STACK_ALIGN);
        argv = sp + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
        envp = argv + (argc + 1);
 
@@ -589,7 +592,7 @@ static int load_flat_file(struct linux_binprm * bprm,
                if (IS_ERR_VALUE(result)) {
                        printk("Unable to read data+bss, errno %d\n", (int)-result);
                        do_munmap(current->mm, textpos, text_len);
-                       do_munmap(current->mm, realdatastart, data_len + extra);
+                       do_munmap(current->mm, realdatastart, len);
                        ret = result;
                        goto err;
                }
@@ -876,7 +879,7 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        stack_len = TOP_OF_ARGS - bprm->p;             /* the strings */
        stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
        stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */
-       stack_len += FLAT_DATA_ALIGN - 1;  /* reserve for upcoming alignment */
+       stack_len += FLAT_STACK_ALIGN - 1;  /* reserve for upcoming alignment */
        
        res = load_flat_file(bprm, &libinfo, 0, &stack_len);
        if (IS_ERR_VALUE(res))
index 7346c96308a581546b7f5773fd94d41f9a3c7345..99d6af8117473b661a64a5f05e58a024570d4fe0 100644 (file)
@@ -706,8 +706,13 @@ retry:
  * @bdev is about to be opened exclusively.  Check @bdev can be opened
  * exclusively and mark that an exclusive open is in progress.  Each
  * successful call to this function must be matched with a call to
- * either bd_claim() or bd_abort_claiming().  If this function
- * succeeds, the matching bd_claim() is guaranteed to succeed.
+ * either bd_finish_claiming() or bd_abort_claiming() (which do not
+ * fail).
+ *
+ * This function is used to gain exclusive access to the block device
+ * without actually causing other exclusive open attempts to fail. It
+ * should be used when the open sequence itself requires exclusive
+ * access but may subsequently fail.
  *
  * CONTEXT:
  * Might sleep.
@@ -734,6 +739,7 @@ static struct block_device *bd_start_claiming(struct block_device *bdev,
                return ERR_PTR(-ENXIO);
 
        whole = bdget_disk(disk, 0);
+       module_put(disk->fops->owner);
        put_disk(disk);
        if (!whole)
                return ERR_PTR(-ENOMEM);
@@ -782,15 +788,46 @@ static void bd_abort_claiming(struct block_device *whole, void *holder)
        __bd_abort_claiming(whole, holder);             /* releases bdev_lock */
 }
 
+/* increment holders when we have a legitimate claim. requires bdev_lock */
+static void __bd_claim(struct block_device *bdev, struct block_device *whole,
+                                       void *holder)
+{
+       /* note that for a whole device bd_holders
+        * will be incremented twice, and bd_holder will
+        * be set to bd_claim before being set to holder
+        */
+       whole->bd_holders++;
+       whole->bd_holder = bd_claim;
+       bdev->bd_holders++;
+       bdev->bd_holder = holder;
+}
+
+/**
+ * bd_finish_claiming - finish claiming a block device
+ * @bdev: block device of interest (passed to bd_start_claiming())
+ * @whole: whole block device returned by bd_start_claiming()
+ * @holder: holder trying to claim @bdev
+ *
+ * Finish a claiming block started by bd_start_claiming().
+ *
+ * CONTEXT:
+ * Grabs and releases bdev_lock.
+ */
+static void bd_finish_claiming(struct block_device *bdev,
+                               struct block_device *whole, void *holder)
+{
+       spin_lock(&bdev_lock);
+       BUG_ON(!bd_may_claim(bdev, whole, holder));
+       __bd_claim(bdev, whole, holder);
+       __bd_abort_claiming(whole, holder); /* not actually an abort */
+}
+
 /**
  * bd_claim - claim a block device
  * @bdev: block device to claim
  * @holder: holder trying to claim @bdev
  *
- * Try to claim @bdev which must have been opened successfully.  This
- * function may be called with or without preceding
- * blk_start_claiming().  In the former case, this function is always
- * successful and terminates the claiming block.
+ * Try to claim @bdev which must have been opened successfully.
  *
  * CONTEXT:
  * Might sleep.
@@ -806,23 +843,10 @@ int bd_claim(struct block_device *bdev, void *holder)
        might_sleep();
 
        spin_lock(&bdev_lock);
-
        res = bd_prepare_to_claim(bdev, whole, holder);
-       if (res == 0) {
-               /* note that for a whole device bd_holders
-                * will be incremented twice, and bd_holder will
-                * be set to bd_claim before being set to holder
-                */
-               whole->bd_holders++;
-               whole->bd_holder = bd_claim;
-               bdev->bd_holders++;
-               bdev->bd_holder = holder;
-       }
-
-       if (whole->bd_claiming)
-               __bd_abort_claiming(whole, holder);     /* releases bdev_lock */
-       else
-               spin_unlock(&bdev_lock);
+       if (res == 0)
+               __bd_claim(bdev, whole, holder);
+       spin_unlock(&bdev_lock);
 
        return res;
 }
@@ -1476,7 +1500,7 @@ static int blkdev_open(struct inode * inode, struct file * filp)
 
        if (whole) {
                if (res == 0)
-                       BUG_ON(bd_claim(bdev, filp) != 0);
+                       bd_finish_claiming(bdev, whole, filp);
                else
                        bd_abort_claiming(whole, filp);
        }
@@ -1712,7 +1736,7 @@ struct block_device *open_bdev_exclusive(const char *path, fmode_t mode, void *h
        if ((mode & FMODE_WRITE) && bdev_read_only(bdev))
                goto out_blkdev_put;
 
-       BUG_ON(bd_claim(bdev, holder) != 0);
+       bd_finish_claiming(bdev, whole, holder);
        return bdev;
 
 out_blkdev_put:
index 8d432cd9d580d39ed2e94bf3be99c17667a8b0dd..2222d161c7b68111431031e007b019d7de629d3e 100644 (file)
@@ -60,6 +60,8 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
                size = __btrfs_getxattr(inode, name, value, size);
                if (size > 0) {
                        acl = posix_acl_from_xattr(value, size);
+                       if (IS_ERR(acl))
+                               return acl;
                        set_cached_acl(inode, type, acl);
                }
                kfree(value);
@@ -160,6 +162,12 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
        int ret;
        struct posix_acl *acl = NULL;
 
+       if (!is_owner_or_cap(dentry->d_inode))
+               return -EPERM;
+
+       if (!IS_POSIXACL(dentry->d_inode))
+               return -EOPNOTSUPP;
+
        if (value) {
                acl = posix_acl_from_xattr(value, size);
                if (acl == NULL) {
index f3b287c22caf2e6855cf89bf780cf0b4b675c902..34f7c375567e38eef3f83843baf0bf2272282008 100644 (file)
@@ -1941,8 +1941,11 @@ struct btrfs_root *open_ctree(struct super_block *sb,
                     btrfs_level_size(tree_root,
                                      btrfs_super_log_root_level(disk_super));
 
-               log_tree_root = kzalloc(sizeof(struct btrfs_root),
-                                                     GFP_NOFS);
+               log_tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+               if (!log_tree_root) {
+                       err = -ENOMEM;
+                       goto fail_trans_kthread;
+               }
 
                __setup_root(nodesize, leafsize, sectorsize, stripesize,
                             log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID);
@@ -1982,6 +1985,10 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location);
        if (!fs_info->fs_root)
                goto fail_trans_kthread;
+       if (IS_ERR(fs_info->fs_root)) {
+               err = PTR_ERR(fs_info->fs_root);
+               goto fail_trans_kthread;
+       }
 
        if (!(sb->s_flags & MS_RDONLY)) {
                down_read(&fs_info->cleanup_work_sem);
index b9080d71991a35cea63d2620d1534234cde6e0a9..32d094002a57132b2113e9e8f02303f6a8b16052 100644 (file)
@@ -4360,7 +4360,8 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
 
        block_rsv = get_block_rsv(trans, root);
        cache = btrfs_lookup_block_group(root->fs_info, buf->start);
-       BUG_ON(block_rsv->space_info != cache->space_info);
+       if (block_rsv->space_info != cache->space_info)
+               goto out;
 
        if (btrfs_header_generation(buf) == trans->transid) {
                if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
index 787b50a16a146eea9bb4ec4202fcdab1f3f4bec0..e354c33df0824592bb9356be4987fd0ddfbbdc71 100644 (file)
@@ -1140,7 +1140,7 @@ int btrfs_sync_file(struct file *file, int datasync)
        /*
         * ok we haven't committed the transaction yet, lets do a commit
         */
-       if (file && file->private_data)
+       if (file->private_data)
                btrfs_ioctl_trans_end(file);
 
        trans = btrfs_start_transaction(root, 0);
@@ -1190,14 +1190,22 @@ static const struct vm_operations_struct btrfs_file_vm_ops = {
 
 static int btrfs_file_mmap(struct file *filp, struct vm_area_struct *vma)
 {
-       vma->vm_ops = &btrfs_file_vm_ops;
+       struct address_space *mapping = filp->f_mapping;
+
+       if (!mapping->a_ops->readpage)
+               return -ENOEXEC;
+
        file_accessed(filp);
+       vma->vm_ops = &btrfs_file_vm_ops;
+       vma->vm_flags |= VM_CAN_NONLINEAR;
+
        return 0;
 }
 
 const struct file_operations btrfs_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
+       .write          = do_sync_write,
        .aio_read       = generic_file_aio_read,
        .splice_read    = generic_file_splice_read,
        .aio_write      = btrfs_file_aio_write,
index fa6ccc1bfe2a9a73e2de97ed04cac8708efa99f9..1bff92ad474434a535b711abebb14d7a692cabca 100644 (file)
@@ -2673,7 +2673,7 @@ static int check_path_shared(struct btrfs_root *root,
        struct extent_buffer *eb;
        int level;
        int ret;
-       u64 refs;
+       u64 refs = 1;
 
        for (level = 0; level < BTRFS_MAX_LEVEL; level++) {
                if (!path->nodes[level])
@@ -6884,7 +6884,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
                if (em->block_start == EXTENT_MAP_HOLE ||
                    (cur_offset >= inode->i_size &&
                     !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
-                       ret = btrfs_prealloc_file_range(inode, 0, cur_offset,
+                       ret = btrfs_prealloc_file_range(inode, mode, cur_offset,
                                                        last_byte - cur_offset,
                                                        1 << inode->i_blkbits,
                                                        offset + len,
index 4cdb98cf26de174e644e7d74e2a97e2fe037f08b..4dbaf89b1337632ac7800b84b183d6cd0ab14242 100644 (file)
@@ -1280,7 +1280,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
        trans = btrfs_start_transaction(root, 0);
        if (IS_ERR(trans)) {
                err = PTR_ERR(trans);
-               goto out;
+               goto out_up_write;
        }
        trans->block_rsv = &root->fs_info->global_block_rsv;
 
@@ -1845,7 +1845,7 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
        dir_id = btrfs_super_root_dir(&root->fs_info->super_copy);
        di = btrfs_lookup_dir_item(trans, root->fs_info->tree_root, path,
                                   dir_id, "default", 7, 1);
-       if (!di) {
+       if (IS_ERR_OR_NULL(di)) {
                btrfs_free_path(path);
                btrfs_end_transaction(trans, root);
                printk(KERN_ERR "Umm, you don't have the default dir item, "
index 05d41e569236330cc8ed8e5e0f8b17566080791c..b37d723b9d4a8a137b05256a85788074b5f03c5e 100644 (file)
@@ -784,16 +784,17 @@ again:
                                struct btrfs_extent_ref_v0 *ref0;
                                ref0 = btrfs_item_ptr(eb, path1->slots[0],
                                                struct btrfs_extent_ref_v0);
-                               root = find_tree_root(rc, eb, ref0);
-                               if (!root->ref_cows)
-                                       cur->cowonly = 1;
                                if (key.objectid == key.offset) {
+                                       root = find_tree_root(rc, eb, ref0);
                                        if (root && !should_ignore_root(root))
                                                cur->root = root;
                                        else
                                                list_add(&cur->list, &useless);
                                        break;
                                }
+                               if (is_cowonly_root(btrfs_ref_root_v0(eb,
+                                                                     ref0)))
+                                       cur->cowonly = 1;
                        }
 #else
                BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY);
index b91ccd972644b48048329806044ebc3c62d1b550..2d958be761c84556b39c60afa39999b0f3fd75d6 100644 (file)
@@ -330,7 +330,6 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 {
        struct btrfs_path *path;
        int ret;
-       u32 refs;
        struct btrfs_root_item *ri;
        struct extent_buffer *leaf;
 
@@ -344,8 +343,6 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        leaf = path->nodes[0];
        ri = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_item);
 
-       refs = btrfs_disk_root_refs(leaf, ri);
-       BUG_ON(refs != 0);
        ret = btrfs_del_item(trans, root, path);
 out:
        btrfs_free_path(path);
index d34b2dfc9628cde65f6181b5ed4043cf8603541c..f2393b39031812c178fd98cb79eb614f3ba6c65a 100644 (file)
@@ -360,6 +360,8 @@ static struct dentry *get_default_root(struct super_block *sb,
         */
        dir_id = btrfs_super_root_dir(&root->fs_info->super_copy);
        di = btrfs_lookup_dir_item(NULL, root, path, dir_id, "default", 7, 0);
+       if (IS_ERR(di))
+               return ERR_CAST(di);
        if (!di) {
                /*
                 * Ok the default dir item isn't there.  This is weird since
@@ -390,8 +392,8 @@ setup_root:
        location.offset = 0;
 
        inode = btrfs_iget(sb, &location, new_root, &new);
-       if (!inode)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
 
        /*
         * If we're just mounting the root most subvol put the inode and return
index ae3e3a3064451f7b49fedaa3931120ff1af6d169..619b61655ee5dd4496ca4ec6374849c09f892817 100644 (file)
@@ -981,6 +981,46 @@ static int send_cap_msg(struct ceph_mds_session *session,
        return 0;
 }
 
+static void __queue_cap_release(struct ceph_mds_session *session,
+                               u64 ino, u64 cap_id, u32 migrate_seq,
+                               u32 issue_seq)
+{
+       struct ceph_msg *msg;
+       struct ceph_mds_cap_release *head;
+       struct ceph_mds_cap_item *item;
+
+       spin_lock(&session->s_cap_lock);
+       BUG_ON(!session->s_num_cap_releases);
+       msg = list_first_entry(&session->s_cap_releases,
+                              struct ceph_msg, list_head);
+
+       dout(" adding %llx release to mds%d msg %p (%d left)\n",
+            ino, session->s_mds, msg, session->s_num_cap_releases);
+
+       BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE);
+       head = msg->front.iov_base;
+       head->num = cpu_to_le32(le32_to_cpu(head->num) + 1);
+       item = msg->front.iov_base + msg->front.iov_len;
+       item->ino = cpu_to_le64(ino);
+       item->cap_id = cpu_to_le64(cap_id);
+       item->migrate_seq = cpu_to_le32(migrate_seq);
+       item->seq = cpu_to_le32(issue_seq);
+
+       session->s_num_cap_releases--;
+
+       msg->front.iov_len += sizeof(*item);
+       if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
+               dout(" release msg %p full\n", msg);
+               list_move_tail(&msg->list_head, &session->s_cap_releases_done);
+       } else {
+               dout(" release msg %p at %d/%d (%d)\n", msg,
+                    (int)le32_to_cpu(head->num),
+                    (int)CEPH_CAPS_PER_RELEASE,
+                    (int)msg->front.iov_len);
+       }
+       spin_unlock(&session->s_cap_lock);
+}
+
 /*
  * Queue cap releases when an inode is dropped from our cache.  Since
  * inode is about to be destroyed, there is no need for i_lock.
@@ -994,41 +1034,9 @@ void ceph_queue_caps_release(struct inode *inode)
        while (p) {
                struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
                struct ceph_mds_session *session = cap->session;
-               struct ceph_msg *msg;
-               struct ceph_mds_cap_release *head;
-               struct ceph_mds_cap_item *item;
 
-               spin_lock(&session->s_cap_lock);
-               BUG_ON(!session->s_num_cap_releases);
-               msg = list_first_entry(&session->s_cap_releases,
-                                      struct ceph_msg, list_head);
-
-               dout(" adding %p release to mds%d msg %p (%d left)\n",
-                    inode, session->s_mds, msg, session->s_num_cap_releases);
-
-               BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE);
-               head = msg->front.iov_base;
-               head->num = cpu_to_le32(le32_to_cpu(head->num) + 1);
-               item = msg->front.iov_base + msg->front.iov_len;
-               item->ino = cpu_to_le64(ceph_ino(inode));
-               item->cap_id = cpu_to_le64(cap->cap_id);
-               item->migrate_seq = cpu_to_le32(cap->mseq);
-               item->seq = cpu_to_le32(cap->issue_seq);
-
-               session->s_num_cap_releases--;
-
-               msg->front.iov_len += sizeof(*item);
-               if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
-                       dout(" release msg %p full\n", msg);
-                       list_move_tail(&msg->list_head,
-                                      &session->s_cap_releases_done);
-               } else {
-                       dout(" release msg %p at %d/%d (%d)\n", msg,
-                            (int)le32_to_cpu(head->num),
-                            (int)CEPH_CAPS_PER_RELEASE,
-                            (int)msg->front.iov_len);
-               }
-               spin_unlock(&session->s_cap_lock);
+               __queue_cap_release(session, ceph_ino(inode), cap->cap_id,
+                                   cap->mseq, cap->issue_seq);
                p = rb_next(p);
                __ceph_remove_cap(cap);
        }
@@ -2655,7 +2663,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        struct ceph_mds_caps *h;
        int mds = session->s_mds;
        int op;
-       u32 seq;
+       u32 seq, mseq;
        struct ceph_vino vino;
        u64 cap_id;
        u64 size, max_size;
@@ -2675,6 +2683,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        vino.snap = CEPH_NOSNAP;
        cap_id = le64_to_cpu(h->cap_id);
        seq = le32_to_cpu(h->seq);
+       mseq = le32_to_cpu(h->migrate_seq);
        size = le64_to_cpu(h->size);
        max_size = le64_to_cpu(h->max_size);
 
@@ -2689,6 +2698,18 @@ void ceph_handle_caps(struct ceph_mds_session *session,
             vino.snap, inode);
        if (!inode) {
                dout(" i don't have ino %llx\n", vino.ino);
+
+               if (op == CEPH_CAP_OP_IMPORT)
+                       __queue_cap_release(session, vino.ino, cap_id,
+                                           mseq, seq);
+
+               /*
+                * send any full release message to try to move things
+                * along for the mds (who clearly thinks we still have this
+                * cap).
+                */
+               ceph_add_cap_releases(mdsc, session, -1);
+               ceph_send_cap_releases(mdsc, session);
                goto done;
        }
 
@@ -2714,7 +2735,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        spin_lock(&inode->i_lock);
        cap = __get_cap_for_mds(ceph_inode(inode), mds);
        if (!cap) {
-               dout("no cap on %p ino %llx.%llx from mds%d, releasing\n",
+               dout(" no cap on %p ino %llx.%llx from mds%d\n",
                     inode, ceph_ino(inode), ceph_snap(inode), mds);
                spin_unlock(&inode->i_lock);
                goto done;
index 226f5a50d36294163e44de833c6949967c04348d..ab47f46ca28285b179f4e307375a88555c17ef21 100644 (file)
@@ -827,7 +827,7 @@ static void ceph_set_dentry_offset(struct dentry *dn)
 
        spin_lock(&dcache_lock);
        spin_lock(&dn->d_lock);
-       list_move_tail(&dir->d_subdirs, &dn->d_u.d_child);
+       list_move(&dn->d_u.d_child, &dir->d_subdirs);
        dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
             dn->d_u.d_child.prev, dn->d_u.d_child.next);
        spin_unlock(&dn->d_lock);
index b49f12822cbcb77b1dab660f4d1aa602df5effb9..1766947fc07ab0892027fd5a3fc042e552310275 100644 (file)
@@ -1066,9 +1066,9 @@ static int trim_caps(struct ceph_mds_client *mdsc,
  *
  * Called under s_mutex.
  */
-static int add_cap_releases(struct ceph_mds_client *mdsc,
-                           struct ceph_mds_session *session,
-                           int extra)
+int ceph_add_cap_releases(struct ceph_mds_client *mdsc,
+                         struct ceph_mds_session *session,
+                         int extra)
 {
        struct ceph_msg *msg;
        struct ceph_mds_cap_release *head;
@@ -1176,8 +1176,8 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq)
 /*
  * called under s_mutex
  */
-static void send_cap_releases(struct ceph_mds_client *mdsc,
-                      struct ceph_mds_session *session)
+void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
+                           struct ceph_mds_session *session)
 {
        struct ceph_msg *msg;
 
@@ -1980,7 +1980,7 @@ out_err:
        }
        mutex_unlock(&mdsc->mutex);
 
-       add_cap_releases(mdsc, req->r_session, -1);
+       ceph_add_cap_releases(mdsc, req->r_session, -1);
        mutex_unlock(&session->s_mutex);
 
        /* kick calling process */
@@ -2433,6 +2433,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
        struct ceph_dentry_info *di;
        int mds = session->s_mds;
        struct ceph_mds_lease *h = msg->front.iov_base;
+       u32 seq;
        struct ceph_vino vino;
        int mask;
        struct qstr dname;
@@ -2446,6 +2447,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
        vino.ino = le64_to_cpu(h->ino);
        vino.snap = CEPH_NOSNAP;
        mask = le16_to_cpu(h->mask);
+       seq = le32_to_cpu(h->seq);
        dname.name = (void *)h + sizeof(*h) + sizeof(u32);
        dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32);
        if (dname.len != get_unaligned_le32(h+1))
@@ -2456,8 +2458,9 @@ static void handle_lease(struct ceph_mds_client *mdsc,
 
        /* lookup inode */
        inode = ceph_find_inode(sb, vino);
-       dout("handle_lease '%s', mask %d, ino %llx %p\n",
-            ceph_lease_op_name(h->action), mask, vino.ino, inode);
+       dout("handle_lease %s, mask %d, ino %llx %p %.*s\n",
+            ceph_lease_op_name(h->action), mask, vino.ino, inode,
+            dname.len, dname.name);
        if (inode == NULL) {
                dout("handle_lease no inode %llx\n", vino.ino);
                goto release;
@@ -2482,7 +2485,8 @@ static void handle_lease(struct ceph_mds_client *mdsc,
        switch (h->action) {
        case CEPH_MDS_LEASE_REVOKE:
                if (di && di->lease_session == session) {
-                       h->seq = cpu_to_le32(di->lease_seq);
+                       if (ceph_seq_cmp(di->lease_seq, seq) > 0)
+                               h->seq = cpu_to_le32(di->lease_seq);
                        __ceph_mdsc_drop_dentry_lease(dentry);
                }
                release = 1;
@@ -2496,7 +2500,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
                        unsigned long duration =
                                le32_to_cpu(h->duration_ms) * HZ / 1000;
 
-                       di->lease_seq = le32_to_cpu(h->seq);
+                       di->lease_seq = seq;
                        dentry->d_time = di->lease_renew_from + duration;
                        di->lease_renew_after = di->lease_renew_from +
                                (duration >> 1);
@@ -2686,10 +2690,10 @@ static void delayed_work(struct work_struct *work)
                        send_renew_caps(mdsc, s);
                else
                        ceph_con_keepalive(&s->s_con);
-               add_cap_releases(mdsc, s, -1);
+               ceph_add_cap_releases(mdsc, s, -1);
                if (s->s_state == CEPH_MDS_SESSION_OPEN ||
                    s->s_state == CEPH_MDS_SESSION_HUNG)
-                       send_cap_releases(mdsc, s);
+                       ceph_send_cap_releases(mdsc, s);
                mutex_unlock(&s->s_mutex);
                ceph_put_mds_session(s);
 
index d9936c4f12122a6a670a198a8a50249d06c27543..b292fa42a66d8026b49a0217ffc0b4e89f381497 100644 (file)
@@ -322,6 +322,12 @@ static inline void ceph_mdsc_put_request(struct ceph_mds_request *req)
        kref_put(&req->r_kref, ceph_mdsc_release_request);
 }
 
+extern int ceph_add_cap_releases(struct ceph_mds_client *mdsc,
+                                struct ceph_mds_session *session,
+                                int extra);
+extern void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
+                                  struct ceph_mds_session *session);
+
 extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc);
 
 extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
index 21c62e9b7d1d6d4c816d252a3155706d25752ccf..07a539906e67c821a2db3e0c6717c0957d3bbecf 100644 (file)
@@ -400,6 +400,8 @@ static void release_generic_request(struct kref *kref)
                ceph_msg_put(req->reply);
        if (req->request)
                ceph_msg_put(req->request);
+
+       kfree(req);
 }
 
 static void put_generic_request(struct ceph_mon_generic_request *req)
index 4e0bee240b9dbf10c9a14e9c13ac6a4867d1d0c2..fa87f51e38e112a38f8a95d87ac4c96e02e7d7ef 100644 (file)
@@ -89,7 +89,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
 
        buf->f_files = le64_to_cpu(st.num_objects);
        buf->f_ffree = -1;
-       buf->f_namelen = PATH_MAX;
+       buf->f_namelen = NAME_MAX;
        buf->f_frsize = PAGE_CACHE_SIZE;
 
        /* leave fsid little-endian, regardless of host endianness */
@@ -926,7 +926,7 @@ static int ceph_compare_super(struct super_block *sb, void *data)
 /*
  * construct our own bdi so we can control readahead, etc.
  */
-static atomic_long_t bdi_seq = ATOMIC_INIT(0);
+static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
 
 static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client)
 {
index 78c02eb4cb1f107f6c2503acc4f6d56f7e1b1524..484e52bb40bb20436956167a511567147b6136c5 100644 (file)
@@ -473,14 +473,24 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data)
        return 0;
 }
 
+void cifs_drop_inode(struct inode *inode)
+{
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+               return generic_drop_inode(inode);
+
+       return generic_delete_inode(inode);
+}
+
 static const struct super_operations cifs_super_ops = {
        .put_super = cifs_put_super,
        .statfs = cifs_statfs,
        .alloc_inode = cifs_alloc_inode,
        .destroy_inode = cifs_destroy_inode,
-/*     .drop_inode         = generic_delete_inode,
-       .delete_inode   = cifs_delete_inode,  */  /* Do not need above two
-       functions unless later we add lazy close of inodes or unless the
+       .drop_inode     = cifs_drop_inode,
+/*     .delete_inode   = cifs_delete_inode,  */  /* Do not need above
+       function unless later we add lazy close of inodes or unless the
        kernel forgets to call us with the same number of releases (closes)
        as opens */
        .show_options = cifs_show_options,
index fb1657e0fdb812d204b3a9309e3e245e3032e985..fb6318b81509801a218d8a2248542e427b9516ce 100644 (file)
@@ -106,7 +106,6 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
                                __u16 fileHandle, struct file *file,
                                struct vfsmount *mnt, unsigned int oflags);
 extern int cifs_posix_open(char *full_path, struct inode **pinode,
-                               struct vfsmount *mnt,
                                struct super_block *sb,
                                int mode, int oflags,
                                __u32 *poplock, __u16 *pnetfid, int xid);
index 391816b461ca1872328cec6e9d3ec3abbd7502e0..e7ae78b66fa15b89162b18a12d76c90f48b8b508 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
+#include <linux/file.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #include "cifsglob.h"
@@ -184,12 +185,13 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
        }
        write_unlock(&GlobalSMBSeslock);
 
+       file->private_data = pCifsFile;
+
        return pCifsFile;
 }
 
 int cifs_posix_open(char *full_path, struct inode **pinode,
-                       struct vfsmount *mnt, struct super_block *sb,
-                       int mode, int oflags,
+                       struct super_block *sb, int mode, int oflags,
                        __u32 *poplock, __u16 *pnetfid, int xid)
 {
        int rc;
@@ -258,19 +260,6 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
                cifs_fattr_to_inode(*pinode, &fattr);
        }
 
-       /*
-        * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to
-        * file->private_data.
-        */
-       if (mnt) {
-               struct cifsFileInfo *pfile_info;
-
-               pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt,
-                                              oflags);
-               if (pfile_info == NULL)
-                       rc = -ENOMEM;
-       }
-
 posix_open_ret:
        kfree(presp_data);
        return rc;
@@ -298,7 +287,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
        int create_options = CREATE_NOT_DIR;
        __u32 oplock = 0;
        int oflags;
-       bool posix_create = false;
        /*
         * BB below access is probably too much for mknod to request
         *    but we have to do query and setpathinfo so requesting
@@ -339,7 +327,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
            (CIFS_UNIX_POSIX_PATH_OPS_CAP &
                        le64_to_cpu(tcon->fsUnixInfo.Capability))) {
                rc = cifs_posix_open(full_path, &newinode,
-                       nd ? nd->path.mnt : NULL,
                        inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
                /* EIO could indicate that (posix open) operation is not
                   supported, despite what server claimed in capability
@@ -347,7 +334,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                   handled in posix open */
 
                if (rc == 0) {
-                       posix_create = true;
                        if (newinode == NULL) /* query inode info */
                                goto cifs_create_get_file_info;
                        else /* success, no need to query */
@@ -478,21 +464,28 @@ cifs_create_set_dentry:
        else
                cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
 
-       /* nfsd case - nfs srv does not set nd */
-       if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
-               /* mknod case - do not leave file open */
-               CIFSSMBClose(xid, tcon, fileHandle);
-       } else if (!(posix_create) && (newinode)) {
+       if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
                struct cifsFileInfo *pfile_info;
-               /*
-                * cifs_fill_filedata() takes care of setting cifsFileInfo
-                * pointer to file->private_data.
-                */
-               pfile_info = cifs_new_fileinfo(newinode, fileHandle, NULL,
+               struct file *filp;
+
+               filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
+               if (IS_ERR(filp)) {
+                       rc = PTR_ERR(filp);
+                       CIFSSMBClose(xid, tcon, fileHandle);
+                       goto cifs_create_out;
+               }
+
+               pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
                                               nd->path.mnt, oflags);
-               if (pfile_info == NULL)
+               if (pfile_info == NULL) {
+                       fput(filp);
+                       CIFSSMBClose(xid, tcon, fileHandle);
                        rc = -ENOMEM;
+               }
+       } else {
+               CIFSSMBClose(xid, tcon, fileHandle);
        }
+
 cifs_create_out:
        kfree(buf);
        kfree(full_path);
@@ -636,6 +629,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
        bool posix_open = false;
        struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo *pTcon;
+       struct cifsFileInfo *cfile;
        struct inode *newInode = NULL;
        char *full_path = NULL;
        struct file *filp;
@@ -703,7 +697,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
                if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
                     (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
                     (nd->intent.open.flags & O_CREAT)) {
-                       rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
+                       rc = cifs_posix_open(full_path, &newInode,
                                        parent_dir_inode->i_sb,
                                        nd->intent.open.create_mode,
                                        nd->intent.open.flags, &oplock,
@@ -733,8 +727,25 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
                else
                        direntry->d_op = &cifs_dentry_ops;
                d_add(direntry, newInode);
-               if (posix_open)
-                       filp = lookup_instantiate_filp(nd, direntry, NULL);
+               if (posix_open) {
+                       filp = lookup_instantiate_filp(nd, direntry,
+                                                      generic_file_open);
+                       if (IS_ERR(filp)) {
+                               rc = PTR_ERR(filp);
+                               CIFSSMBClose(xid, pTcon, fileHandle);
+                               goto lookup_out;
+                       }
+
+                       cfile = cifs_new_fileinfo(newInode, fileHandle, filp,
+                                                 nd->path.mnt,
+                                                 nd->intent.open.flags);
+                       if (cfile == NULL) {
+                               fput(filp);
+                               CIFSSMBClose(xid, pTcon, fileHandle);
+                               rc = -ENOMEM;
+                               goto lookup_out;
+                       }
+               }
                /* since paths are not looked up by component - the parent
                   directories are presumed to be good here */
                renew_parental_timestamps(direntry);
@@ -755,6 +766,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
                is a common return code */
        }
 
+lookup_out:
        kfree(full_path);
        FreeXid(xid);
        return ERR_PTR(rc);
index f1ff785b22924d8ccb736fd7794f8c424c2b32c0..409e4f523e61e56aae0e1b892c2a9021ebe3728d 100644 (file)
@@ -162,44 +162,12 @@ psx_client_can_cache:
        return 0;
 }
 
-static struct cifsFileInfo *
-cifs_fill_filedata(struct file *file)
-{
-       struct list_head *tmp;
-       struct cifsFileInfo *pCifsFile = NULL;
-       struct cifsInodeInfo *pCifsInode = NULL;
-
-       /* search inode for this file and fill in file->private_data */
-       pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
-       read_lock(&GlobalSMBSeslock);
-       list_for_each(tmp, &pCifsInode->openFileList) {
-               pCifsFile = list_entry(tmp, struct cifsFileInfo, flist);
-               if ((pCifsFile->pfile == NULL) &&
-                   (pCifsFile->pid == current->tgid)) {
-                       /* mode set in cifs_create */
-
-                       /* needed for writepage */
-                       pCifsFile->pfile = file;
-                       file->private_data = pCifsFile;
-                       break;
-               }
-       }
-       read_unlock(&GlobalSMBSeslock);
-
-       if (file->private_data != NULL) {
-               return pCifsFile;
-       } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
-                       cERROR(1, "could not find file instance for "
-                                  "new file %p", file);
-       return NULL;
-}
-
 /* all arguments to this function must be checked for validity in caller */
-static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
-       struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
+static inline int cifs_open_inode_helper(struct inode *inode,
        struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
        char *full_path, int xid)
 {
+       struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
        struct timespec temp;
        int rc;
 
@@ -213,36 +181,35 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
        /* if not oplocked, invalidate inode pages if mtime or file
           size changed */
        temp = cifs_NTtimeToUnix(buf->LastWriteTime);
-       if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
-                          (file->f_path.dentry->d_inode->i_size ==
+       if (timespec_equal(&inode->i_mtime, &temp) &&
+                          (inode->i_size ==
                            (loff_t)le64_to_cpu(buf->EndOfFile))) {
                cFYI(1, "inode unchanged on server");
        } else {
-               if (file->f_path.dentry->d_inode->i_mapping) {
+               if (inode->i_mapping) {
                        /* BB no need to lock inode until after invalidate
                        since namei code should already have it locked? */
-                       rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
+                       rc = filemap_write_and_wait(inode->i_mapping);
                        if (rc != 0)
-                               CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
+                               pCifsInode->write_behind_rc = rc;
                }
                cFYI(1, "invalidating remote inode since open detected it "
                         "changed");
-               invalidate_remote_inode(file->f_path.dentry->d_inode);
+               invalidate_remote_inode(inode);
        }
 
 client_can_cache:
        if (pTcon->unix_ext)
-               rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
-                       full_path, inode->i_sb, xid);
+               rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
+                                             xid);
        else
-               rc = cifs_get_inode_info(&file->f_path.dentry->d_inode,
-                       full_path, buf, inode->i_sb, xid, NULL);
+               rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
+                                        xid, NULL);
 
        if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
                pCifsInode->clientCanCacheAll = true;
                pCifsInode->clientCanCacheRead = true;
-               cFYI(1, "Exclusive Oplock granted on inode %p",
-                        file->f_path.dentry->d_inode);
+               cFYI(1, "Exclusive Oplock granted on inode %p", inode);
        } else if ((*oplock & 0xF) == OPLOCK_READ)
                pCifsInode->clientCanCacheRead = true;
 
@@ -256,7 +223,7 @@ int cifs_open(struct inode *inode, struct file *file)
        __u32 oplock;
        struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo *tcon;
-       struct cifsFileInfo *pCifsFile;
+       struct cifsFileInfo *pCifsFile = NULL;
        struct cifsInodeInfo *pCifsInode;
        char *full_path = NULL;
        int desiredAccess;
@@ -270,12 +237,6 @@ int cifs_open(struct inode *inode, struct file *file)
        tcon = cifs_sb->tcon;
 
        pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
-       pCifsFile = cifs_fill_filedata(file);
-       if (pCifsFile) {
-               rc = 0;
-               FreeXid(xid);
-               return rc;
-       }
 
        full_path = build_path_from_dentry(file->f_path.dentry);
        if (full_path == NULL) {
@@ -299,8 +260,7 @@ int cifs_open(struct inode *inode, struct file *file)
                int oflags = (int) cifs_posix_convert_flags(file->f_flags);
                oflags |= SMB_O_CREAT;
                /* can not refresh inode info since size could be stale */
-               rc = cifs_posix_open(full_path, &inode, file->f_path.mnt,
-                               inode->i_sb,
+               rc = cifs_posix_open(full_path, &inode, inode->i_sb,
                                cifs_sb->mnt_file_mode /* ignored */,
                                oflags, &oplock, &netfid, xid);
                if (rc == 0) {
@@ -308,9 +268,20 @@ int cifs_open(struct inode *inode, struct file *file)
                        /* no need for special case handling of setting mode
                           on read only files needed here */
 
-                       pCifsFile = cifs_fill_filedata(file);
-                       cifs_posix_open_inode_helper(inode, file, pCifsInode,
-                                                    oplock, netfid);
+                       rc = cifs_posix_open_inode_helper(inode, file,
+                                       pCifsInode, oplock, netfid);
+                       if (rc != 0) {
+                               CIFSSMBClose(xid, tcon, netfid);
+                               goto out;
+                       }
+
+                       pCifsFile = cifs_new_fileinfo(inode, netfid, file,
+                                                       file->f_path.mnt,
+                                                       oflags);
+                       if (pCifsFile == NULL) {
+                               CIFSSMBClose(xid, tcon, netfid);
+                               rc = -ENOMEM;
+                       }
                        goto out;
                } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
                        if (tcon->ses->serverNOS)
@@ -391,17 +362,17 @@ int cifs_open(struct inode *inode, struct file *file)
                goto out;
        }
 
+       rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid);
+       if (rc != 0)
+               goto out;
+
        pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
                                        file->f_flags);
-       file->private_data = pCifsFile;
-       if (file->private_data == NULL) {
+       if (pCifsFile == NULL) {
                rc = -ENOMEM;
                goto out;
        }
 
-       rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, tcon,
-                                   &oplock, buf, full_path, xid);
-
        if (oplock & CIFS_CREATE_ACTION) {
                /* time to set mode which we can not set earlier due to
                   problems creating new read-only files */
@@ -513,8 +484,7 @@ reopen_error_exit:
                        le64_to_cpu(tcon->fsUnixInfo.Capability))) {
                int oflags = (int) cifs_posix_convert_flags(file->f_flags);
                /* can not refresh inode info since size could be stale */
-               rc = cifs_posix_open(full_path, NULL, file->f_path.mnt,
-                               inode->i_sb,
+               rc = cifs_posix_open(full_path, NULL, inode->i_sb,
                                cifs_sb->mnt_file_mode /* ignored */,
                                oflags, &oplock, &netfid, xid);
                if (rc == 0) {
@@ -1952,6 +1922,7 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
                        bytes_read -= PAGE_CACHE_SIZE;
                        continue;
                }
+               page_cache_release(page);
 
                target = kmap_atomic(page, KM_USER0);
 
index 62b324f26a565b112b59d6cdd7f688dbf735e715..6f0683c689523894cb6fae3edd79181876084d42 100644 (file)
@@ -1401,6 +1401,10 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
        if (rc == 0 || rc != -ETXTBSY)
                return rc;
 
+       /* open-file renames don't work across directories */
+       if (to_dentry->d_parent != from_dentry->d_parent)
+               return rc;
+
        /* open the file to be renamed -- we need DELETE perms */
        rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
                         CREATE_NOT_DIR, &srcfid, &oplock, NULL,
index 7707389bdf2c21643e5ad979e44a24ac59057f30..0a57cb7db5dd7554030e599cd111379e343083df 100644 (file)
@@ -730,15 +730,7 @@ ssetup_ntlmssp_authenticate:
 
                /* calculate session key */
                setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
-               if (first_time) /* should this be moved into common code
-                                  with similar ntlmv2 path? */
-               /*   cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
-                               response BB FIXME, v2_sess_key); */
-
-               /* copy session key */
-
-       /*      memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
-               bcc_ptr += LM2_SESS_KEY_SIZE; */
+               /* FIXME: calculate MAC key */
                memcpy(bcc_ptr, (char *)v2_sess_key,
                       sizeof(struct ntlmv2_resp));
                bcc_ptr += sizeof(struct ntlmv2_resp);
index f0b391c50552dc986f93afe1e4c56ce3b777a600..6490d2134ff3e73656b29b6ad5473e339870ae8d 100644 (file)
@@ -626,7 +626,7 @@ ssize_t compat_rw_copy_check_uvector(int type,
                tot_len += len;
                if (tot_len < tmp) /* maths overflow on the compat_ssize_t */
                        goto out;
-               if (!access_ok(vrfy_dir(type), buf, len)) {
+               if (!access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
                        ret = -EFAULT;
                        goto out;
                }
index 41645142b88b4698300cc89bbad15c613e10d6fd..cf78d44a8d6a8bcff1a546e3606058de97e90722 100644 (file)
@@ -72,10 +72,6 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
        if (!sd)
                return -EINVAL;
 
-       error = simple_setattr(dentry, iattr);
-       if (error)
-               return error;
-
        sd_iattr = sd->s_iattr;
        if (!sd_iattr) {
                /* setting attributes for the first time, allocate now */
@@ -89,9 +85,12 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
                sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
                sd->s_iattr = sd_iattr;
        }
-
        /* attributes were changed atleast once in past */
 
+       error = simple_setattr(dentry, iattr);
+       if (error)
+               return error;
+
        if (ia_valid & ATTR_UID)
                sd_iattr->ia_uid = iattr->ia_uid;
        if (ia_valid & ATTR_GID)
index d96047b4a633a86cb7ae711cb29362ac6cda061a..c8c78ba078271163f567c26045afff6cf0b5cd71 100644 (file)
@@ -590,6 +590,8 @@ static void prune_dcache(int count)
                        up_read(&sb->s_umount);
                }
                spin_lock(&sb_lock);
+               /* lock was dropped, must reset next */
+               list_safe_reset_next(sb, n, s_list);
                count -= pruned;
                __put_super(sb);
                /* more work left to do? */
index ca7e2a0ed98a7ec9cbab179178db11f87a8cb9b6..2bcc0431badac87d6a8e9cdb2b0adb737836ebf4 100644 (file)
@@ -200,6 +200,7 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
                                        return error;
                                else {
                                        inode->i_mode = mode;
+                                       inode->i_ctime = CURRENT_TIME_SEC;
                                        mark_inode_dirty(inode);
                                        if (error == 0)
                                                acl = NULL;
index 19214435b75213cbbd6b4ba557194476e30654bd..3675088cb88c53c9f23c01369652d9630f5ced11 100644 (file)
@@ -1552,7 +1552,7 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
                if (error)
                        return error;
        }
-       if (iattr->ia_valid & ATTR_SIZE) {
+       if (iattr->ia_valid & ATTR_SIZE && iattr->ia_size != inode->i_size) {
                error = ext2_setsize(inode, iattr->ia_size);
                if (error)
                        return error;
index 01552abbca3c0f9c47549ed6be812074a7632f1d..8a11fe212183529e225dee8a812264de5053b9d0 100644 (file)
@@ -205,6 +205,7 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
                                        return error;
                                else {
                                        inode->i_mode = mode;
+                                       inode->i_ctime = CURRENT_TIME_SEC;
                                        ext3_mark_inode_dirty(handle, inode);
                                        if (error == 0)
                                                acl = NULL;
index 19df61c321fdfa62e53e53c3af69c0cc41c090e7..42272d67955a413cdd17a53980fe5dac410cceff 100644 (file)
@@ -4942,20 +4942,26 @@ void ext4_set_inode_flags(struct inode *inode)
 /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */
 void ext4_get_inode_flags(struct ext4_inode_info *ei)
 {
-       unsigned int flags = ei->vfs_inode.i_flags;
-
-       ei->i_flags &= ~(EXT4_SYNC_FL|EXT4_APPEND_FL|
-                       EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL|EXT4_DIRSYNC_FL);
-       if (flags & S_SYNC)
-               ei->i_flags |= EXT4_SYNC_FL;
-       if (flags & S_APPEND)
-               ei->i_flags |= EXT4_APPEND_FL;
-       if (flags & S_IMMUTABLE)
-               ei->i_flags |= EXT4_IMMUTABLE_FL;
-       if (flags & S_NOATIME)
-               ei->i_flags |= EXT4_NOATIME_FL;
-       if (flags & S_DIRSYNC)
-               ei->i_flags |= EXT4_DIRSYNC_FL;
+       unsigned int vfs_fl;
+       unsigned long old_fl, new_fl;
+
+       do {
+               vfs_fl = ei->vfs_inode.i_flags;
+               old_fl = ei->i_flags;
+               new_fl = old_fl & ~(EXT4_SYNC_FL|EXT4_APPEND_FL|
+                               EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL|
+                               EXT4_DIRSYNC_FL);
+               if (vfs_fl & S_SYNC)
+                       new_fl |= EXT4_SYNC_FL;
+               if (vfs_fl & S_APPEND)
+                       new_fl |= EXT4_APPEND_FL;
+               if (vfs_fl & S_IMMUTABLE)
+                       new_fl |= EXT4_IMMUTABLE_FL;
+               if (vfs_fl & S_NOATIME)
+                       new_fl |= EXT4_NOATIME_FL;
+               if (vfs_fl & S_DIRSYNC)
+                       new_fl |= EXT4_DIRSYNC_FL;
+       } while (cmpxchg(&ei->i_flags, old_fl, new_fl) != old_fl);
 }
 
 static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
@@ -5191,7 +5197,7 @@ static int ext4_inode_blocks_set(handle_t *handle,
                 */
                raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
                raw_inode->i_blocks_high = 0;
-               ei->i_flags &= ~EXT4_HUGE_FILE_FL;
+               ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE);
                return 0;
        }
        if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE))
@@ -5204,9 +5210,9 @@ static int ext4_inode_blocks_set(handle_t *handle,
                 */
                raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
                raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
-               ei->i_flags &= ~EXT4_HUGE_FILE_FL;
+               ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE);
        } else {
-               ei->i_flags |= EXT4_HUGE_FILE_FL;
+               ext4_set_inode_flag(inode, EXT4_INODE_HUGE_FILE);
                /* i_block is stored in file system block size */
                i_blocks = i_blocks >> (inode->i_blkbits - 9);
                raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
index 3a6c92ac131c449b61f58194087fe376dbd0f32f..52abfa12762a6020c20ee9b62f62227fd16c078f 100644 (file)
@@ -960,6 +960,9 @@ mext_check_arguments(struct inode *orig_inode,
                return -EINVAL;
        }
 
+       if (IS_IMMUTABLE(donor_inode) || IS_APPEND(donor_inode))
+               return -EPERM;
+
        /* Ext4 move extent does not support swapfile */
        if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) {
                ext4_debug("ext4 move extent: The argument files should "
index f74d270ba1554034b02c7532ece41556ca9040c0..9d175d623aabc5e7c99a83e75e6c970a340465c6 100644 (file)
@@ -274,7 +274,7 @@ static int f_setown_ex(struct file *filp, unsigned long arg)
 
        ret = copy_from_user(&owner, owner_p, sizeof(owner));
        if (ret)
-               return ret;
+               return -EFAULT;
 
        switch (owner.type) {
        case F_OWNER_TID:
@@ -332,8 +332,11 @@ static int f_getown_ex(struct file *filp, unsigned long arg)
        }
        read_unlock(&filp->f_owner.lock);
 
-       if (!ret)
+       if (!ret) {
                ret = copy_to_user(owner_p, &owner, sizeof(owner));
+               if (ret)
+                       ret = -EFAULT;
+       }
        return ret;
 }
 
@@ -730,12 +733,14 @@ static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band)
 {
        while (fa) {
                struct fown_struct *fown;
+               unsigned long flags;
+
                if (fa->magic != FASYNC_MAGIC) {
                        printk(KERN_ERR "kill_fasync: bad magic number in "
                               "fasync_struct!\n");
                        return;
                }
-               spin_lock(&fa->fa_lock);
+               spin_lock_irqsave(&fa->fa_lock, flags);
                if (fa->fa_file) {
                        fown = &fa->fa_file->f_owner;
                        /* Don't send SIGURG to processes which have not set a
@@ -744,7 +749,7 @@ static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band)
                        if (!(sig == SIGURG && fown->signum == 0))
                                send_sigio(fown, fa->fa_fd, band);
                }
-               spin_unlock(&fa->fa_lock);
+               spin_unlock_irqrestore(&fa->fa_lock, flags);
                fa = rcu_dereference(fa->fa_next);
        }
 }
index ea8592b906968913499b9847f35389a31e5dc1a3..0609607d395591ad5b23ee52283ad25c85e2bc10 100644 (file)
@@ -45,7 +45,6 @@ struct wb_writeback_args {
        unsigned int for_kupdate:1;
        unsigned int range_cyclic:1;
        unsigned int for_background:1;
-       unsigned int sb_pinned:1;
 };
 
 /*
@@ -64,24 +63,16 @@ struct bdi_work {
 };
 
 enum {
-       WS_USED_B = 0,
-       WS_ONSTACK_B,
+       WS_INPROGRESS = 0,
+       WS_ONSTACK,
 };
 
-#define WS_USED (1 << WS_USED_B)
-#define WS_ONSTACK (1 << WS_ONSTACK_B)
-
-static inline bool bdi_work_on_stack(struct bdi_work *work)
-{
-       return test_bit(WS_ONSTACK_B, &work->state);
-}
-
 static inline void bdi_work_init(struct bdi_work *work,
                                 struct wb_writeback_args *args)
 {
        INIT_RCU_HEAD(&work->rcu_head);
        work->args = *args;
-       work->state = WS_USED;
+       __set_bit(WS_INPROGRESS, &work->state);
 }
 
 /**
@@ -96,43 +87,16 @@ int writeback_in_progress(struct backing_dev_info *bdi)
        return !list_empty(&bdi->work_list);
 }
 
-static void bdi_work_clear(struct bdi_work *work)
-{
-       clear_bit(WS_USED_B, &work->state);
-       smp_mb__after_clear_bit();
-       /*
-        * work can have disappeared at this point. bit waitq functions
-        * should be able to tolerate this, provided bdi_sched_wait does
-        * not dereference it's pointer argument.
-       */
-       wake_up_bit(&work->state, WS_USED_B);
-}
-
 static void bdi_work_free(struct rcu_head *head)
 {
        struct bdi_work *work = container_of(head, struct bdi_work, rcu_head);
 
-       if (!bdi_work_on_stack(work))
-               kfree(work);
-       else
-               bdi_work_clear(work);
-}
-
-static void wb_work_complete(struct bdi_work *work)
-{
-       const enum writeback_sync_modes sync_mode = work->args.sync_mode;
-       int onstack = bdi_work_on_stack(work);
+       clear_bit(WS_INPROGRESS, &work->state);
+       smp_mb__after_clear_bit();
+       wake_up_bit(&work->state, WS_INPROGRESS);
 
-       /*
-        * For allocated work, we can clear the done/seen bit right here.
-        * For on-stack work, we need to postpone both the clear and free
-        * to after the RCU grace period, since the stack could be invalidated
-        * as soon as bdi_work_clear() has done the wakeup.
-        */
-       if (!onstack)
-               bdi_work_clear(work);
-       if (sync_mode == WB_SYNC_NONE || onstack)
-               call_rcu(&work->rcu_head, bdi_work_free);
+       if (!test_bit(WS_ONSTACK, &work->state))
+               kfree(work);
 }
 
 static void wb_clear_pending(struct bdi_writeback *wb, struct bdi_work *work)
@@ -148,7 +112,7 @@ static void wb_clear_pending(struct bdi_writeback *wb, struct bdi_work *work)
                list_del_rcu(&work->list);
                spin_unlock(&bdi->wb_lock);
 
-               wb_work_complete(work);
+               call_rcu(&work->rcu_head, bdi_work_free);
        }
 }
 
@@ -186,15 +150,14 @@ static void bdi_queue_work(struct backing_dev_info *bdi, struct bdi_work *work)
  * Used for on-stack allocated work items. The caller needs to wait until
  * the wb threads have acked the work before it's safe to continue.
  */
-static void bdi_wait_on_work_clear(struct bdi_work *work)
+static void bdi_wait_on_work_done(struct bdi_work *work)
 {
-       wait_on_bit(&work->state, WS_USED_B, bdi_sched_wait,
+       wait_on_bit(&work->state, WS_INPROGRESS, bdi_sched_wait,
                    TASK_UNINTERRUPTIBLE);
 }
 
 static void bdi_alloc_queue_work(struct backing_dev_info *bdi,
-                                struct wb_writeback_args *args,
-                                int wait)
+                                struct wb_writeback_args *args)
 {
        struct bdi_work *work;
 
@@ -206,8 +169,6 @@ static void bdi_alloc_queue_work(struct backing_dev_info *bdi,
        if (work) {
                bdi_work_init(work, args);
                bdi_queue_work(bdi, work);
-               if (wait)
-                       bdi_wait_on_work_clear(work);
        } else {
                struct bdi_writeback *wb = &bdi->wb;
 
@@ -217,72 +178,65 @@ static void bdi_alloc_queue_work(struct backing_dev_info *bdi,
 }
 
 /**
- * bdi_sync_writeback - start and wait for writeback
- * @bdi: the backing device to write from
+ * bdi_queue_work_onstack - start and wait for writeback
  * @sb: write inodes from this super_block
  *
  * Description:
- *   This does WB_SYNC_ALL data integrity writeback and waits for the
- *   IO to complete. Callers must hold the sb s_umount semaphore for
+ *   This function initiates writeback and waits for the operation to
+ *   complete. Callers must hold the sb s_umount semaphore for
  *   reading, to avoid having the super disappear before we are done.
  */
-static void bdi_sync_writeback(struct backing_dev_info *bdi,
-                              struct super_block *sb)
+static void bdi_queue_work_onstack(struct wb_writeback_args *args)
 {
-       struct wb_writeback_args args = {
-               .sb             = sb,
-               .sync_mode      = WB_SYNC_ALL,
-               .nr_pages       = LONG_MAX,
-               .range_cyclic   = 0,
-               /*
-                * Setting sb_pinned is not necessary for WB_SYNC_ALL, but
-                * lets make it explicitly clear.
-                */
-               .sb_pinned      = 1,
-       };
        struct bdi_work work;
 
-       bdi_work_init(&work, &args);
-       work.state |= WS_ONSTACK;
+       bdi_work_init(&work, args);
+       __set_bit(WS_ONSTACK, &work.state);
 
-       bdi_queue_work(bdi, &work);
-       bdi_wait_on_work_clear(&work);
+       bdi_queue_work(args->sb->s_bdi, &work);
+       bdi_wait_on_work_done(&work);
 }
 
 /**
  * bdi_start_writeback - start writeback
  * @bdi: the backing device to write from
- * @sb: write inodes from this super_block
  * @nr_pages: the number of pages to write
- * @sb_locked: caller already holds sb umount sem.
  *
  * Description:
  *   This does WB_SYNC_NONE opportunistic writeback. The IO is only
  *   started when this function returns, we make no guarentees on
- *   completion. Caller specifies whether sb umount sem is held already or not.
+ *   completion. Caller need not hold sb s_umount semaphore.
  *
  */
-void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
-                        long nr_pages, int sb_locked)
+void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages)
 {
        struct wb_writeback_args args = {
-               .sb             = sb,
                .sync_mode      = WB_SYNC_NONE,
                .nr_pages       = nr_pages,
                .range_cyclic   = 1,
-               .sb_pinned      = sb_locked,
        };
 
-       /*
-        * We treat @nr_pages=0 as the special case to do background writeback,
-        * ie. to sync pages until the background dirty threshold is reached.
-        */
-       if (!nr_pages) {
-               args.nr_pages = LONG_MAX;
-               args.for_background = 1;
-       }
+       bdi_alloc_queue_work(bdi, &args);
+}
 
-       bdi_alloc_queue_work(bdi, &args, sb_locked);
+/**
+ * bdi_start_background_writeback - start background writeback
+ * @bdi: the backing device to write from
+ *
+ * Description:
+ *   This does WB_SYNC_NONE background writeback. The IO is only
+ *   started when this function returns, we make no guarentees on
+ *   completion. Caller need not hold sb s_umount semaphore.
+ */
+void bdi_start_background_writeback(struct backing_dev_info *bdi)
+{
+       struct wb_writeback_args args = {
+               .sync_mode      = WB_SYNC_NONE,
+               .nr_pages       = LONG_MAX,
+               .for_background = 1,
+               .range_cyclic   = 1,
+       };
+       bdi_alloc_queue_work(bdi, &args);
 }
 
 /*
@@ -572,48 +526,30 @@ select_queue:
        return ret;
 }
 
-static void unpin_sb_for_writeback(struct super_block *sb)
-{
-       up_read(&sb->s_umount);
-       put_super(sb);
-}
-
-enum sb_pin_state {
-       SB_PINNED,
-       SB_NOT_PINNED,
-       SB_PIN_FAILED
-};
-
 /*
- * For WB_SYNC_NONE writeback, the caller does not have the sb pinned
+ * For background writeback the caller does not have the sb pinned
  * before calling writeback. So make sure that we do pin it, so it doesn't
  * go away while we are writing inodes from it.
  */
-static enum sb_pin_state pin_sb_for_writeback(struct writeback_control *wbc,
-                                             struct super_block *sb)
+static bool pin_sb_for_writeback(struct super_block *sb)
 {
-       /*
-        * Caller must already hold the ref for this
-        */
-       if (wbc->sync_mode == WB_SYNC_ALL || wbc->sb_pinned) {
-               WARN_ON(!rwsem_is_locked(&sb->s_umount));
-               return SB_NOT_PINNED;
-       }
        spin_lock(&sb_lock);
+       if (list_empty(&sb->s_instances)) {
+               spin_unlock(&sb_lock);
+               return false;
+       }
+
        sb->s_count++;
+       spin_unlock(&sb_lock);
+
        if (down_read_trylock(&sb->s_umount)) {
-               if (sb->s_root) {
-                       spin_unlock(&sb_lock);
-                       return SB_PINNED;
-               }
-               /*
-                * umounted, drop rwsem again and fall through to failure
-                */
+               if (sb->s_root)
+                       return true;
                up_read(&sb->s_umount);
        }
-       sb->s_count--;
-       spin_unlock(&sb_lock);
-       return SB_PIN_FAILED;
+
+       put_super(sb);
+       return false;
 }
 
 /*
@@ -692,24 +628,31 @@ static void writeback_inodes_wb(struct bdi_writeback *wb,
                struct inode *inode = list_entry(wb->b_io.prev,
                                                 struct inode, i_list);
                struct super_block *sb = inode->i_sb;
-               enum sb_pin_state state;
 
-               if (wbc->sb && sb != wbc->sb) {
-                       /* super block given and doesn't
-                          match, skip this inode */
-                       redirty_tail(inode);
-                       continue;
-               }
-               state = pin_sb_for_writeback(wbc, sb);
+               if (wbc->sb) {
+                       /*
+                        * We are requested to write out inodes for a specific
+                        * superblock.  This means we already have s_umount
+                        * taken by the caller which also waits for us to
+                        * complete the writeout.
+                        */
+                       if (sb != wbc->sb) {
+                               redirty_tail(inode);
+                               continue;
+                       }
 
-               if (state == SB_PIN_FAILED) {
-                       requeue_io(inode);
-                       continue;
+                       WARN_ON(!rwsem_is_locked(&sb->s_umount));
+
+                       ret = writeback_sb_inodes(sb, wb, wbc);
+               } else {
+                       if (!pin_sb_for_writeback(sb)) {
+                               requeue_io(inode);
+                               continue;
+                       }
+                       ret = writeback_sb_inodes(sb, wb, wbc);
+                       drop_super(sb);
                }
-               ret = writeback_sb_inodes(sb, wb, wbc);
 
-               if (state == SB_PINNED)
-                       unpin_sb_for_writeback(sb);
                if (ret)
                        break;
        }
@@ -769,7 +712,6 @@ static long wb_writeback(struct bdi_writeback *wb,
                .for_kupdate            = args->for_kupdate,
                .for_background         = args->for_background,
                .range_cyclic           = args->range_cyclic,
-               .sb_pinned              = args->sb_pinned,
        };
        unsigned long oldest_jif;
        long wrote = 0;
@@ -912,7 +854,6 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
 
        while ((work = get_next_work_item(bdi, wb)) != NULL) {
                struct wb_writeback_args args = work->args;
-               int post_clear;
 
                /*
                 * Override sync mode, in case we must wait for completion
@@ -920,13 +861,11 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
                if (force_wait)
                        work->args.sync_mode = args.sync_mode = WB_SYNC_ALL;
 
-               post_clear = WB_SYNC_ALL || args.sb_pinned;
-
                /*
                 * If this isn't a data integrity operation, just notify
                 * that we have seen this work and we are now starting it.
                 */
-               if (!post_clear)
+               if (!test_bit(WS_ONSTACK, &work->state))
                        wb_clear_pending(wb, work);
 
                wrote += wb_writeback(wb, &args);
@@ -935,7 +874,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
                 * This is a data integrity writeback, so only do the
                 * notification when we have completed the work.
                 */
-               if (post_clear)
+               if (test_bit(WS_ONSTACK, &work->state))
                        wb_clear_pending(wb, work);
        }
 
@@ -993,42 +932,32 @@ int bdi_writeback_task(struct bdi_writeback *wb)
 }
 
 /*
- * Schedule writeback for all backing devices. This does WB_SYNC_NONE
- * writeback, for integrity writeback see bdi_sync_writeback().
+ * Start writeback of `nr_pages' pages.  If `nr_pages' is zero, write back
+ * the whole world.
  */
-static void bdi_writeback_all(struct super_block *sb, long nr_pages)
+void wakeup_flusher_threads(long nr_pages)
 {
+       struct backing_dev_info *bdi;
        struct wb_writeback_args args = {
-               .sb             = sb,
-               .nr_pages       = nr_pages,
                .sync_mode      = WB_SYNC_NONE,
        };
-       struct backing_dev_info *bdi;
 
-       rcu_read_lock();
+       if (nr_pages) {
+               args.nr_pages = nr_pages;
+       } else {
+               args.nr_pages = global_page_state(NR_FILE_DIRTY) +
+                               global_page_state(NR_UNSTABLE_NFS);
+       }
 
+       rcu_read_lock();
        list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
                if (!bdi_has_dirty_io(bdi))
                        continue;
-
-               bdi_alloc_queue_work(bdi, &args, 0);
+               bdi_alloc_queue_work(bdi, &args);
        }
-
        rcu_read_unlock();
 }
 
-/*
- * Start writeback of `nr_pages' pages.  If `nr_pages' is zero, write back
- * the whole world.
- */
-void wakeup_flusher_threads(long nr_pages)
-{
-       if (nr_pages == 0)
-               nr_pages = global_page_state(NR_FILE_DIRTY) +
-                               global_page_state(NR_UNSTABLE_NFS);
-       bdi_writeback_all(NULL, nr_pages);
-}
-
 static noinline void block_dump___mark_inode_dirty(struct inode *inode)
 {
        if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) {
@@ -1220,18 +1149,6 @@ static void wait_sb_inodes(struct super_block *sb)
        iput(old_inode);
 }
 
-static void __writeback_inodes_sb(struct super_block *sb, int sb_locked)
-{
-       unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY);
-       unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS);
-       long nr_to_write;
-
-       nr_to_write = nr_dirty + nr_unstable +
-                       (inodes_stat.nr_inodes - inodes_stat.nr_unused);
-
-       bdi_start_writeback(sb->s_bdi, sb, nr_to_write, sb_locked);
-}
-
 /**
  * writeback_inodes_sb -       writeback dirty inodes from given super_block
  * @sb: the superblock
@@ -1243,21 +1160,21 @@ static void __writeback_inodes_sb(struct super_block *sb, int sb_locked)
  */
 void writeback_inodes_sb(struct super_block *sb)
 {
-       __writeback_inodes_sb(sb, 0);
-}
-EXPORT_SYMBOL(writeback_inodes_sb);
+       unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY);
+       unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS);
+       struct wb_writeback_args args = {
+               .sb             = sb,
+               .sync_mode      = WB_SYNC_NONE,
+       };
 
-/**
- * writeback_inodes_sb_locked  - writeback dirty inodes from given super_block
- * @sb: the superblock
- *
- * Like writeback_inodes_sb(), except the caller already holds the
- * sb umount sem.
- */
-void writeback_inodes_sb_locked(struct super_block *sb)
-{
-       __writeback_inodes_sb(sb, 1);
+       WARN_ON(!rwsem_is_locked(&sb->s_umount));
+
+       args.nr_pages = nr_dirty + nr_unstable +
+                       (inodes_stat.nr_inodes - inodes_stat.nr_unused);
+
+       bdi_queue_work_onstack(&args);
 }
+EXPORT_SYMBOL(writeback_inodes_sb);
 
 /**
  * writeback_inodes_sb_if_idle -       start writeback if none underway
@@ -1269,7 +1186,9 @@ void writeback_inodes_sb_locked(struct super_block *sb)
 int writeback_inodes_sb_if_idle(struct super_block *sb)
 {
        if (!writeback_in_progress(sb->s_bdi)) {
+               down_read(&sb->s_umount);
                writeback_inodes_sb(sb);
+               up_read(&sb->s_umount);
                return 1;
        } else
                return 0;
@@ -1285,7 +1204,16 @@ EXPORT_SYMBOL(writeback_inodes_sb_if_idle);
  */
 void sync_inodes_sb(struct super_block *sb)
 {
-       bdi_sync_writeback(sb->s_bdi, sb);
+       struct wb_writeback_args args = {
+               .sb             = sb,
+               .sync_mode      = WB_SYNC_ALL,
+               .nr_pages       = LONG_MAX,
+               .range_cyclic   = 0,
+       };
+
+       WARN_ON(!rwsem_is_locked(&sb->s_umount));
+
+       bdi_queue_work_onstack(&args);
        wait_sb_inodes(sb);
 }
 EXPORT_SYMBOL(sync_inodes_sb);
index 47aefd376e54060341d15a31ab5cf96a2755a13e..723b889fd219f5eb6a6f360b807ac8e45881f00a 100644 (file)
@@ -710,30 +710,26 @@ static void fscache_write_op(struct fscache_operation *_op)
                goto superseded;
        }
 
-       if (page) {
-               radix_tree_tag_set(&cookie->stores, page->index,
-                                  FSCACHE_COOKIE_STORING_TAG);
-               radix_tree_tag_clear(&cookie->stores, page->index,
-                                    FSCACHE_COOKIE_PENDING_TAG);
-       }
+       radix_tree_tag_set(&cookie->stores, page->index,
+                          FSCACHE_COOKIE_STORING_TAG);
+       radix_tree_tag_clear(&cookie->stores, page->index,
+                            FSCACHE_COOKIE_PENDING_TAG);
 
        spin_unlock(&cookie->stores_lock);
        spin_unlock(&object->lock);
 
-       if (page) {
-               fscache_set_op_state(&op->op, "Store");
-               fscache_stat(&fscache_n_store_pages);
-               fscache_stat(&fscache_n_cop_write_page);
-               ret = object->cache->ops->write_page(op, page);
-               fscache_stat_d(&fscache_n_cop_write_page);
-               fscache_set_op_state(&op->op, "EndWrite");
-               fscache_end_page_write(object, page);
-               if (ret < 0) {
-                       fscache_set_op_state(&op->op, "Abort");
-                       fscache_abort_object(object);
-               } else {
-                       fscache_enqueue_operation(&op->op);
-               }
+       fscache_set_op_state(&op->op, "Store");
+       fscache_stat(&fscache_n_store_pages);
+       fscache_stat(&fscache_n_cop_write_page);
+       ret = object->cache->ops->write_page(op, page);
+       fscache_stat_d(&fscache_n_cop_write_page);
+       fscache_set_op_state(&op->op, "EndWrite");
+       fscache_end_page_write(object, page);
+       if (ret < 0) {
+               fscache_set_op_state(&op->op, "Abort");
+               fscache_abort_object(object);
+       } else {
+               fscache_enqueue_operation(&op->op);
        }
 
        _leave("");
index a33aab6b5e683cf988932fdd9f732f5381751541..54a92fd02bbd63b2d75543f59bd816b4d738e2e4 100644 (file)
@@ -234,8 +234,9 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
                        if (inode->i_mode != mode) {
                                struct iattr attr;
 
-                               attr.ia_valid = ATTR_MODE;
+                               attr.ia_valid = ATTR_MODE | ATTR_CTIME;
                                attr.ia_mode = mode;
+                               attr.ia_ctime = CURRENT_TIME_SEC;
                                rc = jffs2_do_setattr(inode, &attr);
                                if (rc < 0)
                                        return rc;
index 7aa4417e085f2870acd84598c2a5bd0c3654b20c..166062a682304be3361b93ffe5efffa3456fdc96 100644 (file)
@@ -222,15 +222,18 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
        dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
 
        jffs2_free_raw_inode(ri);
-       d_instantiate(dentry, inode);
 
        D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
                  inode->i_ino, inode->i_mode, inode->i_nlink,
                  f->inocache->pino_nlink, inode->i_mapping->nrpages));
+
+       d_instantiate(dentry, inode);
+       unlock_new_inode(inode);
        return 0;
 
  fail:
        make_bad_inode(inode);
+       unlock_new_inode(inode);
        iput(inode);
        jffs2_free_raw_inode(ri);
        return ret;
@@ -360,8 +363,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
                /* Eeek. Wave bye bye */
                mutex_unlock(&f->sem);
                jffs2_complete_reservation(c);
-               jffs2_clear_inode(inode);
-               return PTR_ERR(fn);
+               ret = PTR_ERR(fn);
+               goto fail;
        }
 
        /* We use f->target field to store the target path. */
@@ -370,8 +373,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
                printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);
                mutex_unlock(&f->sem);
                jffs2_complete_reservation(c);
-               jffs2_clear_inode(inode);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto fail;
        }
 
        memcpy(f->target, target, targetlen + 1);
@@ -386,30 +389,24 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
        jffs2_complete_reservation(c);
 
        ret = jffs2_init_security(inode, dir_i);
-       if (ret) {
-               jffs2_clear_inode(inode);
-               return ret;
-       }
+       if (ret)
+               goto fail;
+
        ret = jffs2_init_acl_post(inode);
-       if (ret) {
-               jffs2_clear_inode(inode);
-               return ret;
-       }
+       if (ret)
+               goto fail;
 
        ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
                                  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
-       if (ret) {
-               /* Eep. */
-               jffs2_clear_inode(inode);
-               return ret;
-       }
+       if (ret)
+               goto fail;
 
        rd = jffs2_alloc_raw_dirent();
        if (!rd) {
                /* Argh. Now we treat it like a normal delete */
                jffs2_complete_reservation(c);
-               jffs2_clear_inode(inode);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto fail;
        }
 
        dir_f = JFFS2_INODE_INFO(dir_i);
@@ -437,8 +434,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
                jffs2_complete_reservation(c);
                jffs2_free_raw_dirent(rd);
                mutex_unlock(&dir_f->sem);
-               jffs2_clear_inode(inode);
-               return PTR_ERR(fd);
+               ret = PTR_ERR(fd);
+               goto fail;
        }
 
        dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
@@ -453,7 +450,14 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
        jffs2_complete_reservation(c);
 
        d_instantiate(dentry, inode);
+       unlock_new_inode(inode);
        return 0;
+
+ fail:
+       make_bad_inode(inode);
+       unlock_new_inode(inode);
+       iput(inode);
+       return ret;
 }
 
 
@@ -519,8 +523,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
                /* Eeek. Wave bye bye */
                mutex_unlock(&f->sem);
                jffs2_complete_reservation(c);
-               jffs2_clear_inode(inode);
-               return PTR_ERR(fn);
+               ret = PTR_ERR(fn);
+               goto fail;
        }
        /* No data here. Only a metadata node, which will be
           obsoleted by the first data write
@@ -531,30 +535,24 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
        jffs2_complete_reservation(c);
 
        ret = jffs2_init_security(inode, dir_i);
-       if (ret) {
-               jffs2_clear_inode(inode);
-               return ret;
-       }
+       if (ret)
+               goto fail;
+
        ret = jffs2_init_acl_post(inode);
-       if (ret) {
-               jffs2_clear_inode(inode);
-               return ret;
-       }
+       if (ret)
+               goto fail;
 
        ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
                                  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
-       if (ret) {
-               /* Eep. */
-               jffs2_clear_inode(inode);
-               return ret;
-       }
+       if (ret)
+               goto fail;
 
        rd = jffs2_alloc_raw_dirent();
        if (!rd) {
                /* Argh. Now we treat it like a normal delete */
                jffs2_complete_reservation(c);
-               jffs2_clear_inode(inode);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto fail;
        }
 
        dir_f = JFFS2_INODE_INFO(dir_i);
@@ -582,8 +580,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
                jffs2_complete_reservation(c);
                jffs2_free_raw_dirent(rd);
                mutex_unlock(&dir_f->sem);
-               jffs2_clear_inode(inode);
-               return PTR_ERR(fd);
+               ret = PTR_ERR(fd);
+               goto fail;
        }
 
        dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
@@ -599,7 +597,14 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
        jffs2_complete_reservation(c);
 
        d_instantiate(dentry, inode);
+       unlock_new_inode(inode);
        return 0;
+
+ fail:
+       make_bad_inode(inode);
+       unlock_new_inode(inode);
+       iput(inode);
+       return ret;
 }
 
 static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
@@ -693,8 +698,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
                /* Eeek. Wave bye bye */
                mutex_unlock(&f->sem);
                jffs2_complete_reservation(c);
-               jffs2_clear_inode(inode);
-               return PTR_ERR(fn);
+               ret = PTR_ERR(fn);
+               goto fail;
        }
        /* No data here. Only a metadata node, which will be
           obsoleted by the first data write
@@ -705,30 +710,24 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
        jffs2_complete_reservation(c);
 
        ret = jffs2_init_security(inode, dir_i);
-       if (ret) {
-               jffs2_clear_inode(inode);
-               return ret;
-       }
+       if (ret)
+               goto fail;
+
        ret = jffs2_init_acl_post(inode);
-       if (ret) {
-               jffs2_clear_inode(inode);
-               return ret;
-       }
+       if (ret)
+               goto fail;
 
        ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
                                  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
-       if (ret) {
-               /* Eep. */
-               jffs2_clear_inode(inode);
-               return ret;
-       }
+       if (ret)
+               goto fail;
 
        rd = jffs2_alloc_raw_dirent();
        if (!rd) {
                /* Argh. Now we treat it like a normal delete */
                jffs2_complete_reservation(c);
-               jffs2_clear_inode(inode);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto fail;
        }
 
        dir_f = JFFS2_INODE_INFO(dir_i);
@@ -759,8 +758,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
                jffs2_complete_reservation(c);
                jffs2_free_raw_dirent(rd);
                mutex_unlock(&dir_f->sem);
-               jffs2_clear_inode(inode);
-               return PTR_ERR(fd);
+               ret = PTR_ERR(fd);
+               goto fail;
        }
 
        dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
@@ -775,8 +774,14 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
        jffs2_complete_reservation(c);
 
        d_instantiate(dentry, inode);
-
+       unlock_new_inode(inode);
        return 0;
+
+ fail:
+       make_bad_inode(inode);
+       unlock_new_inode(inode);
+       iput(inode);
+       return ret;
 }
 
 static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
index 8bc2c80ab159592dbcf8f43050566ac64de009b0..459d39d1ea0be8ad487903321a8e77fba82d30c6 100644 (file)
@@ -465,7 +465,12 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
        inode->i_blocks = 0;
        inode->i_size = 0;
 
-       insert_inode_hash(inode);
+       if (insert_inode_locked(inode) < 0) {
+               make_bad_inode(inode);
+               unlock_new_inode(inode);
+               iput(inode);
+               return ERR_PTR(-EINVAL);
+       }
 
        return inode;
 }
index 09e1016eb774556c0e69a5a4129da275410565c5..dcaf972cbf1b6d81f29e17d2a1fccd259a794777 100644 (file)
@@ -489,7 +489,8 @@ int simple_write_end(struct file *file, struct address_space *mapping,
  * unique inode values later for this filesystem, then you must take care
  * to pass it an appropriate max_reserved value to avoid collisions.
  */
-int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
+int simple_fill_super(struct super_block *s, unsigned long magic,
+                     struct tree_descr *files)
 {
        struct inode *inode;
        struct dentry *root;
index 91969589131c562d0dfaddc4d3f1905611262a23..1dbf921ca44b42de92c6dda06e014b395dfcdae9 100644 (file)
@@ -75,10 +75,6 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n)
        if (!IS_ERR(page))
                kmap(page);
        return page;
-
-fail:
-       dir_put_page(page);
-       return ERR_PTR(-EIO);
 }
 
 static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
index 7ec9b34a59f8df96f376a60a13a3750e96ca766c..d25b5257b7a1a38380457804333a384cf47f3939 100644 (file)
@@ -1286,6 +1286,55 @@ static void nfs4_session_set_rwsize(struct nfs_server *server)
 #endif /* CONFIG_NFS_V4_1 */
 }
 
+static int nfs4_server_common_setup(struct nfs_server *server,
+               struct nfs_fh *mntfh)
+{
+       struct nfs_fattr *fattr;
+       int error;
+
+       BUG_ON(!server->nfs_client);
+       BUG_ON(!server->nfs_client->rpc_ops);
+       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+       fattr = nfs_alloc_fattr();
+       if (fattr == NULL)
+               return -ENOMEM;
+
+       /* We must ensure the session is initialised first */
+       error = nfs4_init_session(server);
+       if (error < 0)
+               goto out;
+
+       /* Probe the root fh to retrieve its FSID and filehandle */
+       error = nfs4_get_rootfh(server, mntfh);
+       if (error < 0)
+               goto out;
+
+       dprintk("Server FSID: %llx:%llx\n",
+                       (unsigned long long) server->fsid.major,
+                       (unsigned long long) server->fsid.minor);
+       dprintk("Mount FH: %d\n", mntfh->size);
+
+       nfs4_session_set_rwsize(server);
+
+       error = nfs_probe_fsinfo(server, mntfh, fattr);
+       if (error < 0)
+               goto out;
+
+       if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
+               server->namelen = NFS4_MAXNAMLEN;
+
+       spin_lock(&nfs_client_lock);
+       list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
+       list_add_tail(&server->master_link, &nfs_volume_list);
+       spin_unlock(&nfs_client_lock);
+
+       server->mount_time = jiffies;
+out:
+       nfs_free_fattr(fattr);
+       return error;
+}
+
 /*
  * Create a version 4 volume record
  */
@@ -1346,7 +1395,6 @@ error:
 struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
                                      struct nfs_fh *mntfh)
 {
-       struct nfs_fattr *fattr;
        struct nfs_server *server;
        int error;
 
@@ -1356,55 +1404,19 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
        if (!server)
                return ERR_PTR(-ENOMEM);
 
-       error = -ENOMEM;
-       fattr = nfs_alloc_fattr();
-       if (fattr == NULL)
-               goto error;
-
        /* set up the general RPC client */
        error = nfs4_init_server(server, data);
        if (error < 0)
                goto error;
 
-       BUG_ON(!server->nfs_client);
-       BUG_ON(!server->nfs_client->rpc_ops);
-       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
-
-       error = nfs4_init_session(server);
-       if (error < 0)
-               goto error;
-
-       /* Probe the root fh to retrieve its FSID */
-       error = nfs4_get_rootfh(server, mntfh);
+       error = nfs4_server_common_setup(server, mntfh);
        if (error < 0)
                goto error;
 
-       dprintk("Server FSID: %llx:%llx\n",
-               (unsigned long long) server->fsid.major,
-               (unsigned long long) server->fsid.minor);
-       dprintk("Mount FH: %d\n", mntfh->size);
-
-       nfs4_session_set_rwsize(server);
-
-       error = nfs_probe_fsinfo(server, mntfh, fattr);
-       if (error < 0)
-               goto error;
-
-       if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
-               server->namelen = NFS4_MAXNAMLEN;
-
-       spin_lock(&nfs_client_lock);
-       list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
-       list_add_tail(&server->master_link, &nfs_volume_list);
-       spin_unlock(&nfs_client_lock);
-
-       server->mount_time = jiffies;
        dprintk("<-- nfs4_create_server() = %p\n", server);
-       nfs_free_fattr(fattr);
        return server;
 
 error:
-       nfs_free_fattr(fattr);
        nfs_free_server(server);
        dprintk("<-- nfs4_create_server() = error %d\n", error);
        return ERR_PTR(error);
@@ -1418,7 +1430,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
 {
        struct nfs_client *parent_client;
        struct nfs_server *server, *parent_server;
-       struct nfs_fattr *fattr;
        int error;
 
        dprintk("--> nfs4_create_referral_server()\n");
@@ -1427,11 +1438,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
        if (!server)
                return ERR_PTR(-ENOMEM);
 
-       error = -ENOMEM;
-       fattr = nfs_alloc_fattr();
-       if (fattr == NULL)
-               goto error;
-
        parent_server = NFS_SB(data->sb);
        parent_client = parent_server->nfs_client;
 
@@ -1456,40 +1462,14 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
        if (error < 0)
                goto error;
 
-       BUG_ON(!server->nfs_client);
-       BUG_ON(!server->nfs_client->rpc_ops);
-       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
-
-       /* Probe the root fh to retrieve its FSID and filehandle */
-       error = nfs4_get_rootfh(server, mntfh);
-       if (error < 0)
-               goto error;
-
-       /* probe the filesystem info for this server filesystem */
-       error = nfs_probe_fsinfo(server, mntfh, fattr);
+       error = nfs4_server_common_setup(server, mntfh);
        if (error < 0)
                goto error;
 
-       if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
-               server->namelen = NFS4_MAXNAMLEN;
-
-       dprintk("Referral FSID: %llx:%llx\n",
-               (unsigned long long) server->fsid.major,
-               (unsigned long long) server->fsid.minor);
-
-       spin_lock(&nfs_client_lock);
-       list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
-       list_add_tail(&server->master_link, &nfs_volume_list);
-       spin_unlock(&nfs_client_lock);
-
-       server->mount_time = jiffies;
-
-       nfs_free_fattr(fattr);
        dprintk("<-- nfs_create_referral_server() = %p\n", server);
        return server;
 
 error:
-       nfs_free_fattr(fattr);
        nfs_free_server(server);
        dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
        return ERR_PTR(error);
index 7428f7d6273bf2bd512c03e4419487e6deffc6fb..a70e446e1605fa43fb1b23b96418d8296773109f 100644 (file)
@@ -146,7 +146,7 @@ int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh)
                goto out;
        }
 
-       if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_MODE)
+       if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE)
                        || !S_ISDIR(fsinfo.fattr->mode)) {
                printk(KERN_ERR "nfs4_get_rootfh:"
                       " getroot encountered non-directory\n");
index 6bdef28efa33ff07561da0f92f492bc1b5d78046..65c8dae4b267f5622fb936dbaeb61f1f448c41a5 100644 (file)
@@ -862,8 +862,8 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
                bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
                *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
                *p++ = cpu_to_be32(0);
-               *p++ = cpu_to_be32(iap->ia_mtime.tv_sec);
-               *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
+               *p++ = cpu_to_be32(iap->ia_atime.tv_sec);
+               *p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
        }
        else if (iap->ia_valid & ATTR_ATIME) {
                bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
index 04214fc5c30457ea290a2a15e0f87a5f184aea65..f9df16de4a56b84e18ddb3288f9606bd2cd2cd49 100644 (file)
@@ -570,6 +570,22 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
        nfs_show_mountd_netid(m, nfss, showdefaults);
 }
 
+#ifdef CONFIG_NFS_V4
+static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
+                                   int showdefaults)
+{
+       struct nfs_client *clp = nfss->nfs_client;
+
+       seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
+       seq_printf(m, ",minorversion=%u", clp->cl_minorversion);
+}
+#else
+static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
+                                   int showdefaults)
+{
+}
+#endif
+
 /*
  * Describe the mount options in force on this server representation
  */
@@ -631,11 +647,9 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
 
        if (version != 4)
                nfs_show_mountd_options(m, nfss, showdefaults);
+       else
+               nfs_show_nfsv4_options(m, nfss, showdefaults);
 
-#ifdef CONFIG_NFS_V4
-       if (clp->rpc_ops->version == 4)
-               seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
-#endif
        if (nfss->options & NFS_OPTION_FSCACHE)
                seq_printf(m, ",fsc");
 }
index 12f7109720c235cc92cd2464621f7cbff893848e..4a2734758778117a92a16163644a11606cb7d602 100644 (file)
@@ -4122,8 +4122,8 @@ nfs4_state_shutdown(void)
        nfs4_lock_state();
        nfs4_release_reclaim();
        __nfs4_state_shutdown();
-       nfsd4_destroy_callback_queue();
        nfs4_unlock_state();
+       nfsd4_destroy_callback_queue();
 }
 
 /*
index ebbf3b6b24577128c3182072d34933770d56e644..3c111120b619ff20c7b74a81e081801d4965b08e 100644 (file)
@@ -443,8 +443,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
        if (size_change)
                put_write_access(inode);
        if (!err)
-               if (EX_ISSYNC(fhp->fh_export))
-                       write_inode_now(inode, 1);
+               commit_metadata(fhp);
 out:
        return err;
 
index af638d59e3bf5ef07064e57173dcc2f82328724f..43c8c5b541fd84c09d0af119b8f555a247d04522 100644 (file)
@@ -75,8 +75,6 @@ struct nilfs_btree_path {
 
 extern struct kmem_cache *nilfs_btree_path_cache;
 
-int nilfs_btree_path_cache_init(void);
-void nilfs_btree_path_cache_destroy(void);
 int nilfs_btree_init(struct nilfs_bmap *);
 int nilfs_btree_convert_and_insert(struct nilfs_bmap *, __u64, __u64,
                                   const __u64 *, const __u64 *, int);
index fdf1c3b6d6739c6cc76bd451ee8230b573800acf..85fbb66455e2ed43d4004724e24c4930bf4af48f 100644 (file)
@@ -127,8 +127,6 @@ struct nilfs_segment_buffer {
 
 extern struct kmem_cache *nilfs_segbuf_cachep;
 
-int __init nilfs_init_segbuf_cache(void);
-void nilfs_destroy_segbuf_cache(void);
 struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *);
 void nilfs_segbuf_free(struct nilfs_segment_buffer *);
 void nilfs_segbuf_map(struct nilfs_segment_buffer *, __u64, unsigned long,
index dca142361ccfcac8f038453ec689ee61a97012fa..01e20dbb217d9a746a1324b474251e0a8c0100cf 100644 (file)
@@ -221,8 +221,6 @@ enum {
 extern struct kmem_cache *nilfs_transaction_cachep;
 
 /* segment.c */
-extern int nilfs_init_transaction_cache(void);
-extern void nilfs_destroy_transaction_cache(void);
 extern void nilfs_relax_pressure_in_lock(struct super_block *);
 
 extern int nilfs_construct_segment(struct super_block *);
index 03b34b738993fb39c006c1b3248e4f36488e4558..414ef68931cf48dc0443892cae12bcab91262660 100644 (file)
@@ -1130,13 +1130,13 @@ static void nilfs_segbuf_init_once(void *obj)
 
 static void nilfs_destroy_cachep(void)
 {
-        if (nilfs_inode_cachep)
+       if (nilfs_inode_cachep)
                kmem_cache_destroy(nilfs_inode_cachep);
-        if (nilfs_transaction_cachep)
+       if (nilfs_transaction_cachep)
                kmem_cache_destroy(nilfs_transaction_cachep);
-        if (nilfs_segbuf_cachep)
+       if (nilfs_segbuf_cachep)
                kmem_cache_destroy(nilfs_segbuf_cachep);
-        if (nilfs_btree_path_cache)
+       if (nilfs_btree_path_cache)
                kmem_cache_destroy(nilfs_btree_path_cache);
 }
 
index 40650021fc24f633deb020ec10b26492315c27f9..d8b6e4259b80022cb824326f4ce2c665089b5818 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/fs.h>
 #include <linux/types.h>
-#include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/bitops.h>
 #include <linux/list.h>
index db6eaaba0dd81fb777f2b64f1e385d40eb3f1819..279eef96c51cdf28a81d4f0c3d0d702a71dc5a1c 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
 
 /*
  * The max size that a non-root user is allowed to grow the pipe. Can
- * be set by root in /proc/sys/fs/pipe-max-pages
+ * be set by root in /proc/sys/fs/pipe-max-size
  */
-unsigned int pipe_max_pages = PIPE_DEF_BUFFERS * 16;
+unsigned int pipe_max_size = 1048576;
+
+/*
+ * Minimum pipe size, as required by POSIX
+ */
+unsigned int pipe_min_size = PAGE_SIZE;
 
 /*
  * We use a start+len construction, which provides full use of the 
@@ -1118,26 +1123,20 @@ SYSCALL_DEFINE1(pipe, int __user *, fildes)
  * Allocate a new array of pipe buffers and copy the info over. Returns the
  * pipe size if successful, or return -ERROR on error.
  */
-static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
+static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
 {
        struct pipe_buffer *bufs;
 
-       /*
-        * Must be a power-of-2 currently
-        */
-       if (!is_power_of_2(arg))
-               return -EINVAL;
-
        /*
         * We can shrink the pipe, if arg >= pipe->nrbufs. Since we don't
         * expect a lot of shrink+grow operations, just free and allocate
         * again like we would do for growing. If the pipe currently
         * contains more buffers than arg, then return busy.
         */
-       if (arg < pipe->nrbufs)
+       if (nr_pages < pipe->nrbufs)
                return -EBUSY;
 
-       bufs = kcalloc(arg, sizeof(struct pipe_buffer), GFP_KERNEL);
+       bufs = kcalloc(nr_pages, sizeof(struct pipe_buffer), GFP_KERNEL);
        if (unlikely(!bufs))
                return -ENOMEM;
 
@@ -1146,20 +1145,56 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
         * and adjust the indexes.
         */
        if (pipe->nrbufs) {
-               const unsigned int tail = pipe->nrbufs & (pipe->buffers - 1);
-               const unsigned int head = pipe->nrbufs - tail;
+               unsigned int tail;
+               unsigned int head;
+
+               tail = pipe->curbuf + pipe->nrbufs;
+               if (tail < pipe->buffers)
+                       tail = 0;
+               else
+                       tail &= (pipe->buffers - 1);
 
+               head = pipe->nrbufs - tail;
                if (head)
                        memcpy(bufs, pipe->bufs + pipe->curbuf, head * sizeof(struct pipe_buffer));
                if (tail)
-                       memcpy(bufs + head, pipe->bufs + pipe->curbuf, tail * sizeof(struct pipe_buffer));
+                       memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
        }
 
        pipe->curbuf = 0;
        kfree(pipe->bufs);
        pipe->bufs = bufs;
-       pipe->buffers = arg;
-       return arg;
+       pipe->buffers = nr_pages;
+       return nr_pages * PAGE_SIZE;
+}
+
+/*
+ * Currently we rely on the pipe array holding a power-of-2 number
+ * of pages.
+ */
+static inline unsigned int round_pipe_size(unsigned int size)
+{
+       unsigned long nr_pages;
+
+       nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       return roundup_pow_of_two(nr_pages) << PAGE_SHIFT;
+}
+
+/*
+ * This should work even if CONFIG_PROC_FS isn't set, as proc_dointvec_minmax
+ * will return an error.
+ */
+int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
+                size_t *lenp, loff_t *ppos)
+{
+       int ret;
+
+       ret = proc_dointvec_minmax(table, write, buf, lenp, ppos);
+       if (ret < 0 || !write)
+               return ret;
+
+       pipe_max_size = round_pipe_size(pipe_max_size);
+       return ret;
 }
 
 long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -1174,23 +1209,25 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
        mutex_lock(&pipe->inode->i_mutex);
 
        switch (cmd) {
-       case F_SETPIPE_SZ:
-               if (!capable(CAP_SYS_ADMIN) && arg > pipe_max_pages) {
-                       ret = -EINVAL;
+       case F_SETPIPE_SZ: {
+               unsigned int size, nr_pages;
+
+               size = round_pipe_size(arg);
+               nr_pages = size >> PAGE_SHIFT;
+
+               ret = -EINVAL;
+               if (!nr_pages)
                        goto out;
-               }
-               /*
-                * The pipe needs to be at least 2 pages large to
-                * guarantee POSIX behaviour.
-                */
-               if (arg < 2) {
-                       ret = -EINVAL;
+
+               if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
+                       ret = -EPERM;
                        goto out;
                }
-               ret = pipe_set_size(pipe, arg);
+               ret = pipe_set_size(pipe, nr_pages);
                break;
+               }
        case F_GETPIPE_SZ:
-               ret = pipe->buffers;
+               ret = pipe->buffers * PAGE_SIZE;
                break;
        default:
                ret = -EINVAL;
index ce94801f48cafefce01dcc37da6f0037b77de3e5..d9396a4fc7ff2dc209269e70fe7170d07eb1f5bb 100644 (file)
@@ -209,6 +209,9 @@ void proc_device_tree_add_node(struct device_node *np,
        for (pp = np->properties; pp != NULL; pp = pp->next) {
                p = pp->name;
 
+               if (strchr(p, '/'))
+                       continue;
+
                if (duplicate_name(de, p))
                        p = fixup_name(np, de, p);
 
index 46d4b5d72bd33d2e01b9c5e731e8842e616f70f9..cb6306e638435e27a3d883dd84e7fe172029b87f 100644 (file)
@@ -122,11 +122,20 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
        return size;
 }
 
+static void pad_len_spaces(struct seq_file *m, int len)
+{
+       len = 25 + sizeof(void*) * 6 - len;
+       if (len < 1)
+               len = 1;
+       seq_printf(m, "%*c", len, ' ');
+}
+
 /*
  * display a single VMA to a sequenced file
  */
 static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
 {
+       struct mm_struct *mm = vma->vm_mm;
        unsigned long ino = 0;
        struct file *file;
        dev_t dev = 0;
@@ -155,11 +164,14 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
                   MAJOR(dev), MINOR(dev), ino, &len);
 
        if (file) {
-               len = 25 + sizeof(void *) * 6 - len;
-               if (len < 1)
-                       len = 1;
-               seq_printf(m, "%*c", len, ' ');
+               pad_len_spaces(m, len);
                seq_path(m, &file->f_path, "");
+       } else if (mm) {
+               if (vma->vm_start <= mm->start_stack &&
+                       vma->vm_end >= mm->start_stack) {
+                       pad_len_spaces(m, len);
+                       seq_puts(m, "[stack]");
+               }
        }
 
        seq_putc(m, '\n');
index ac22b00d86c3fab51fe3f39cc6cb50a8e7bbcc59..740e6b9faf7ab2e10e0ebfc68725d0d05e0b547f 100644 (file)
@@ -354,7 +354,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
                                break;
 
                        error = add_to_page_cache_lru(page, mapping, index,
-                                               mapping_gfp_mask(mapping));
+                                               GFP_KERNEL);
                        if (unlikely(error)) {
                                page_cache_release(page);
                                if (error == -EEXIST)
index 5c35bc7a499e19c97b0f8eba3a91a8224a46ffe4..938119ab8dcbc28f3f9853bc0808d6d70cd51d55 100644 (file)
@@ -374,6 +374,8 @@ void sync_supers(void)
                        up_read(&sb->s_umount);
 
                        spin_lock(&sb_lock);
+                       /* lock was dropped, must reset next */
+                       list_safe_reset_next(sb, n, s_list);
                        __put_super(sb);
                }
        }
@@ -405,6 +407,8 @@ void iterate_supers(void (*f)(struct super_block *, void *), void *arg)
                up_read(&sb->s_umount);
 
                spin_lock(&sb_lock);
+               /* lock was dropped, must reset next */
+               list_safe_reset_next(sb, n, s_list);
                __put_super(sb);
        }
        spin_unlock(&sb_lock);
@@ -585,6 +589,8 @@ static void do_emergency_remount(struct work_struct *work)
                }
                up_write(&sb->s_umount);
                spin_lock(&sb_lock);
+               /* lock was dropped, must reset next */
+               list_safe_reset_next(sb, n, s_list);
                __put_super(sb);
        }
        spin_unlock(&sb_lock);
index c9f83f480ec55ec751d41021c73c9b3aa8c0b99a..15aa6f03b2da11e5282c564d8d674374d4882a49 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -42,7 +42,7 @@ static int __sync_filesystem(struct super_block *sb, int wait)
        if (wait)
                sync_inodes_sb(sb);
        else
-               writeback_inodes_sb_locked(sb);
+               writeback_inodes_sb(sb);
 
        if (sb->s_op->sync_fs)
                sb->s_op->sync_fs(sb, wait);
index bde1a4c3679a3c38bb5005a473fce4c8e3037e54..0835a3b70e03b01738a8ef18493e1c6180432acd 100644 (file)
@@ -117,11 +117,13 @@ int sysfs_setattr(struct dentry *dentry, struct iattr *iattr)
        if (error)
                goto out;
 
+       error = sysfs_sd_setattr(sd, iattr);
+       if (error)
+               goto out;
+
        /* this ignores size changes */
        generic_setattr(inode, iattr);
 
-       error = sysfs_sd_setattr(sd, iattr);
-
 out:
        mutex_unlock(&sysfs_mutex);
        return error;
index bbd69bdb0fa8cc9ccba41fec291fa13af43f796f..fcc498ec9b337afdcb96582fce07734c9a3cb46d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/buffer_head.h>
+#include <linux/writeback.h>
 #include "sysv.h"
 
 /* We don't trust the value of
@@ -139,6 +140,9 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
        struct inode *inode;
        sysv_ino_t ino;
        unsigned count;
+       struct writeback_control wbc = {
+               .sync_mode = WB_SYNC_NONE
+       };
 
        inode = new_inode(sb);
        if (!inode)
@@ -168,7 +172,7 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
 
-       sysv_write_inode(inode, 0);     /* ensure inode not allocated again */
+       sysv_write_inode(inode, &wbc);  /* ensure inode not allocated again */
        mark_inode_dirty(inode);        /* cleared by sysv_write_inode() */
        /* That's it. */
        unlock_super(sb);
index 076ca50e99336fad10e256ddc3d103ae93fd527a..c8ff0d1ae5d3e04f7f14d8a8b63df33a87b16a35 100644 (file)
@@ -62,7 +62,9 @@
  */
 static void shrink_liability(struct ubifs_info *c, int nr_to_write)
 {
+       down_read(&c->vfs_sb->s_umount);
        writeback_inodes_sb(c->vfs_sb);
+       up_read(&c->vfs_sb->s_umount);
 }
 
 /**
index 089eaca860b4d0fd2792360eda1c89616c5b0dfc..34640d6dbdcb8e6d5879c50a3acafed0cc819708 100644 (file)
@@ -1332,6 +1332,21 @@ xfs_vm_writepage(
 
        trace_xfs_writepage(inode, page, 0);
 
+       /*
+        * Refuse to write the page out if we are called from reclaim context.
+        *
+        * This is primarily to avoid stack overflows when called from deep
+        * used stacks in random callers for direct reclaim, but disabling
+        * reclaim for kswap is a nice side-effect as kswapd causes rather
+        * suboptimal I/O patters, too.
+        *
+        * This should really be done by the core VM, but until that happens
+        * filesystems like XFS, btrfs and ext4 have to take care of this
+        * by themselves.
+        */
+       if (current->flags & PF_MEMALLOC)
+               goto out_fail;
+
        /*
         * We need a transaction if:
         *  1. There are delalloc buffers on the page
@@ -1366,14 +1381,6 @@ xfs_vm_writepage(
        if (!page_has_buffers(page))
                create_empty_buffers(page, 1 << inode->i_blkbits, 0);
 
-
-       /*
-        *  VM calculation for nr_to_write seems off.  Bump it way
-        *  up, this gets simple streaming writes zippy again.
-        *  To be reviewed again after Jens' writeback changes.
-        */
-       wbc->nr_to_write *= 4;
-
        /*
         * Convert delayed allocate, unwritten or unmapped space
         * to real space and flush out to disk.
index 846b75aeb2abe2b260a8efda2a15a73a2b8c18ab..e7839ee49e43656d0d1edfa7011ce8d9eb0e97b2 100644 (file)
@@ -128,13 +128,12 @@ xfs_nfs_get_inode(
                return ERR_PTR(-ESTALE);
 
        /*
-        * The XFS_IGET_BULKSTAT means that an invalid inode number is just
-        * fine and not an indication of a corrupted filesystem.  Because
-        * clients can send any kind of invalid file handle, e.g. after
-        * a restore on the server we have to deal with this case gracefully.
+        * The XFS_IGET_UNTRUSTED means that an invalid inode number is just
+        * fine and not an indication of a corrupted filesystem as clients can
+        * send invalid file handles and we have to handle it gracefully..
         */
-       error = xfs_iget(mp, NULL, ino, XFS_IGET_BULKSTAT,
-                        XFS_ILOCK_SHARED, &ip, 0);
+       error = xfs_iget(mp, NULL, ino, XFS_IGET_UNTRUSTED,
+                        XFS_ILOCK_SHARED, &ip);
        if (error) {
                /*
                 * EINVAL means the inode cluster doesn't exist anymore.
index 699b60cbab9c0da98deb5ca1f1b5839ee726d4b2..e59a8106283069b24bb9fb4b5f0ea5bec92d8ede 100644 (file)
@@ -679,10 +679,9 @@ xfs_ioc_bulkstat(
                error = xfs_bulkstat_single(mp, &inlast,
                                                bulkreq.ubuffer, &done);
        else    /* XFS_IOC_FSBULKSTAT */
-               error = xfs_bulkstat(mp, &inlast, &count,
-                       (bulkstat_one_pf)xfs_bulkstat_one, NULL,
-                       sizeof(xfs_bstat_t), bulkreq.ubuffer,
-                       BULKSTAT_FG_QUICK, &done);
+               error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one,
+                                    sizeof(xfs_bstat_t), bulkreq.ubuffer,
+                                    &done);
 
        if (error)
                return -error;
index 9287135e9bfcedf7ab0f563d5c14bfe9d309e8e5..52ed49e6465cff0eee12844c13b169583cc1411c 100644 (file)
@@ -237,15 +237,12 @@ xfs_bulkstat_one_compat(
        xfs_ino_t       ino,            /* inode number to get data for */
        void            __user *buffer, /* buffer to place output in */
        int             ubsize,         /* size of buffer */
-       void            *private_data,  /* my private data */
-       xfs_daddr_t     bno,            /* starting bno of inode cluster */
        int             *ubused,        /* bytes used by me */
-       void            *dibuff,        /* on-disk inode buffer */
        int             *stat)          /* BULKSTAT_RV_... */
 {
        return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,
-                                   xfs_bulkstat_one_fmt_compat, bno,
-                                   ubused, dibuff, stat);
+                                   xfs_bulkstat_one_fmt_compat,
+                                   ubused, stat);
 }
 
 /* copied from xfs_ioctl.c */
@@ -298,13 +295,11 @@ xfs_compat_ioc_bulkstat(
                int res;
 
                error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer,
-                               sizeof(compat_xfs_bstat_t),
-                               NULL, 0, NULL, NULL, &res);
+                               sizeof(compat_xfs_bstat_t), 0, &res);
        } else if (cmd == XFS_IOC_FSBULKSTAT_32) {
                error = xfs_bulkstat(mp, &inlast, &count,
-                       xfs_bulkstat_one_compat, NULL,
-                       sizeof(compat_xfs_bstat_t), bulkreq.ubuffer,
-                       BULKSTAT_FG_QUICK, &done);
+                       xfs_bulkstat_one_compat, sizeof(compat_xfs_bstat_t),
+                       bulkreq.ubuffer, &done);
        } else
                error = XFS_ERROR(EINVAL);
        if (error)
index 9c8019c78c9221ce80617a61db98bfe3a5b0e135..44f0b2de153eb6c4cf77b36c54278f36166d59ba 100644 (file)
@@ -585,11 +585,20 @@ xfs_vn_fallocate(
        bf.l_len = len;
 
        xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
+       /* check the new inode size is valid before allocating */
+       if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+           offset + len > i_size_read(inode)) {
+               new_size = offset + len;
+               error = inode_newsize_ok(inode, new_size);
+               if (error)
+                       goto out_unlock;
+       }
+
        error = -xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf,
                                       0, XFS_ATTR_NOLOCK);
-       if (!error && !(mode & FALLOC_FL_KEEP_SIZE) &&
-           offset + len > i_size_read(inode))
-               new_size = offset + len;
+       if (error)
+               goto out_unlock;
 
        /* Change file size if needed */
        if (new_size) {
@@ -600,6 +609,7 @@ xfs_vn_fallocate(
                error = -xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK);
        }
 
+out_unlock:
        xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 out_error:
        return error;
index 9ac8aea91529ed403920f746f9d7f52decc2802f..067cafbfc6357fee83a5adbf265e74ab93eeb999 100644 (file)
@@ -23,7 +23,6 @@
 #include "xfs_ag.h"
 #include "xfs_mount.h"
 #include "xfs_quota.h"
-#include "xfs_log.h"
 #include "xfs_trans.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_inode.h"
index 3884e20bc14e523276e855a51e97167ba3f68cbc..ef7f0218bccb45779157128139ab552e8b423832 100644 (file)
@@ -164,10 +164,6 @@ xfs_inode_ag_iterator(
                struct xfs_perag        *pag;
 
                pag = xfs_perag_get(mp, ag);
-               if (!pag->pag_ici_init) {
-                       xfs_perag_put(pag);
-                       continue;
-               }
                error = xfs_inode_ag_walk(mp, pag, execute, flags, tag,
                                                exclusive, &nr);
                xfs_perag_put(pag);
@@ -867,12 +863,7 @@ xfs_reclaim_inode_shrink(
        down_read(&xfs_mount_list_lock);
        list_for_each_entry(mp, &xfs_mount_list, m_mplist) {
                for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {
-
                        pag = xfs_perag_get(mp, ag);
-                       if (!pag->pag_ici_init) {
-                               xfs_perag_put(pag);
-                               continue;
-                       }
                        reclaimable += pag->pag_ici_reclaimable;
                        xfs_perag_put(pag);
                }
index 207fa77f63ae3139e2fa3d2b975d321c6e6e3059..d12be8470cbac741dcdc42ba402cb2e228dd93a2 100644 (file)
@@ -50,7 +50,6 @@
 #include "quota/xfs_dquot_item.h"
 #include "quota/xfs_dquot.h"
 #include "xfs_log_recover.h"
-#include "xfs_buf_item.h"
 #include "xfs_inode_item.h"
 
 /*
index ff6bc797baf290a03ee411a05c8733ecb4ed030c..73d5aa117384bc1e8c626012dba881e02a5deb57 100644 (file)
@@ -82,33 +82,6 @@ DECLARE_EVENT_CLASS(xfs_attr_list_class,
        )
 )
 
-#define DEFINE_PERAG_REF_EVENT(name) \
-TRACE_EVENT(name, \
-       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int refcount, \
-                unsigned long caller_ip), \
-       TP_ARGS(mp, agno, refcount, caller_ip), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_agnumber_t, agno) \
-               __field(int, refcount) \
-               __field(unsigned long, caller_ip) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = mp->m_super->s_dev; \
-               __entry->agno = agno; \
-               __entry->refcount = refcount; \
-               __entry->caller_ip = caller_ip; \
-       ), \
-       TP_printk("dev %d:%d agno %u refcount %d caller %pf", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->agno, \
-                 __entry->refcount, \
-                 (char *)__entry->caller_ip) \
-);
-
-DEFINE_PERAG_REF_EVENT(xfs_perag_get)
-DEFINE_PERAG_REF_EVENT(xfs_perag_put)
-
 #define DEFINE_ATTR_LIST_EVENT(name) \
 DEFINE_EVENT(xfs_attr_list_class, name, \
        TP_PROTO(struct xfs_attr_list_context *ctx), \
@@ -122,6 +95,37 @@ DEFINE_ATTR_LIST_EVENT(xfs_attr_list_add);
 DEFINE_ATTR_LIST_EVENT(xfs_attr_list_wrong_blk);
 DEFINE_ATTR_LIST_EVENT(xfs_attr_list_notfound);
 
+DECLARE_EVENT_CLASS(xfs_perag_class,
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int refcount,
+                unsigned long caller_ip),
+       TP_ARGS(mp, agno, refcount, caller_ip),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_agnumber_t, agno)
+               __field(int, refcount)
+               __field(unsigned long, caller_ip)
+       ),
+       TP_fast_assign(
+               __entry->dev = mp->m_super->s_dev;
+               __entry->agno = agno;
+               __entry->refcount = refcount;
+               __entry->caller_ip = caller_ip;
+       ),
+       TP_printk("dev %d:%d agno %u refcount %d caller %pf",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->agno,
+                 __entry->refcount,
+                 (char *)__entry->caller_ip)
+);
+
+#define DEFINE_PERAG_REF_EVENT(name)   \
+DEFINE_EVENT(xfs_perag_class, name,    \
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int refcount,       \
+                unsigned long caller_ip),                                      \
+       TP_ARGS(mp, agno, refcount, caller_ip))
+DEFINE_PERAG_REF_EVENT(xfs_perag_get);
+DEFINE_PERAG_REF_EVENT(xfs_perag_put);
+
 TRACE_EVENT(xfs_attr_list_node_descend,
        TP_PROTO(struct xfs_attr_list_context *ctx,
                 struct xfs_da_node_entry *btree),
@@ -775,165 +779,181 @@ DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_enter);
 DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_exit);
 DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_sub);
 
-#define DEFINE_RW_EVENT(name) \
-TRACE_EVENT(name, \
-       TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), \
-       TP_ARGS(ip, count, offset, flags), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-               __field(xfs_fsize_t, size) \
-               __field(xfs_fsize_t, new_size) \
-               __field(loff_t, offset) \
-               __field(size_t, count) \
-               __field(int, flags) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = VFS_I(ip)->i_sb->s_dev; \
-               __entry->ino = ip->i_ino; \
-               __entry->size = ip->i_d.di_size; \
-               __entry->new_size = ip->i_new_size; \
-               __entry->offset = offset; \
-               __entry->count = count; \
-               __entry->flags = flags; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
-                 "offset 0x%llx count 0x%zx ioflags %s", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->ino, \
-                 __entry->size, \
-                 __entry->new_size, \
-                 __entry->offset, \
-                 __entry->count, \
-                 __print_flags(__entry->flags, "|", XFS_IO_FLAGS)) \
+DECLARE_EVENT_CLASS(xfs_file_class,
+       TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags),
+       TP_ARGS(ip, count, offset, flags),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(xfs_fsize_t, size)
+               __field(xfs_fsize_t, new_size)
+               __field(loff_t, offset)
+               __field(size_t, count)
+               __field(int, flags)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->size = ip->i_d.di_size;
+               __entry->new_size = ip->i_new_size;
+               __entry->offset = offset;
+               __entry->count = count;
+               __entry->flags = flags;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
+                 "offset 0x%llx count 0x%zx ioflags %s",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->size,
+                 __entry->new_size,
+                 __entry->offset,
+                 __entry->count,
+                 __print_flags(__entry->flags, "|", XFS_IO_FLAGS))
 )
+
+#define DEFINE_RW_EVENT(name)          \
+DEFINE_EVENT(xfs_file_class, name,     \
+       TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), \
+       TP_ARGS(ip, count, offset, flags))
 DEFINE_RW_EVENT(xfs_file_read);
 DEFINE_RW_EVENT(xfs_file_buffered_write);
 DEFINE_RW_EVENT(xfs_file_direct_write);
 DEFINE_RW_EVENT(xfs_file_splice_read);
 DEFINE_RW_EVENT(xfs_file_splice_write);
 
-
-#define DEFINE_PAGE_EVENT(name) \
-TRACE_EVENT(name, \
-       TP_PROTO(struct inode *inode, struct page *page, unsigned long off), \
-       TP_ARGS(inode, page, off), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-               __field(pgoff_t, pgoff) \
-               __field(loff_t, size) \
-               __field(unsigned long, offset) \
-               __field(int, delalloc) \
-               __field(int, unmapped) \
-               __field(int, unwritten) \
-       ), \
-       TP_fast_assign( \
-               int delalloc = -1, unmapped = -1, unwritten = -1; \
-       \
-               if (page_has_buffers(page)) \
-                       xfs_count_page_state(page, &delalloc, \
-                                            &unmapped, &unwritten); \
-               __entry->dev = inode->i_sb->s_dev; \
-               __entry->ino = XFS_I(inode)->i_ino; \
-               __entry->pgoff = page_offset(page); \
-               __entry->size = i_size_read(inode); \
-               __entry->offset = off; \
-               __entry->delalloc = delalloc; \
-               __entry->unmapped = unmapped; \
-               __entry->unwritten = unwritten; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx pgoff 0x%lx size 0x%llx offset %lx " \
-                 "delalloc %d unmapped %d unwritten %d", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->ino, \
-                 __entry->pgoff, \
-                 __entry->size, \
-                 __entry->offset, \
-                 __entry->delalloc, \
-                 __entry->unmapped, \
-                 __entry->unwritten) \
+DECLARE_EVENT_CLASS(xfs_page_class,
+       TP_PROTO(struct inode *inode, struct page *page, unsigned long off),
+       TP_ARGS(inode, page, off),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(pgoff_t, pgoff)
+               __field(loff_t, size)
+               __field(unsigned long, offset)
+               __field(int, delalloc)
+               __field(int, unmapped)
+               __field(int, unwritten)
+       ),
+       TP_fast_assign(
+               int delalloc = -1, unmapped = -1, unwritten = -1;
+
+               if (page_has_buffers(page))
+                       xfs_count_page_state(page, &delalloc,
+                                            &unmapped, &unwritten);
+               __entry->dev = inode->i_sb->s_dev;
+               __entry->ino = XFS_I(inode)->i_ino;
+               __entry->pgoff = page_offset(page);
+               __entry->size = i_size_read(inode);
+               __entry->offset = off;
+               __entry->delalloc = delalloc;
+               __entry->unmapped = unmapped;
+               __entry->unwritten = unwritten;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx pgoff 0x%lx size 0x%llx offset %lx "
+                 "delalloc %d unmapped %d unwritten %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->pgoff,
+                 __entry->size,
+                 __entry->offset,
+                 __entry->delalloc,
+                 __entry->unmapped,
+                 __entry->unwritten)
 )
+
+#define DEFINE_PAGE_EVENT(name)                \
+DEFINE_EVENT(xfs_page_class, name,     \
+       TP_PROTO(struct inode *inode, struct page *page, unsigned long off),    \
+       TP_ARGS(inode, page, off))
 DEFINE_PAGE_EVENT(xfs_writepage);
 DEFINE_PAGE_EVENT(xfs_releasepage);
 DEFINE_PAGE_EVENT(xfs_invalidatepage);
 
-#define DEFINE_IOMAP_EVENT(name) \
-TRACE_EVENT(name, \
-       TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count, \
-                int flags, struct xfs_bmbt_irec *irec), \
-       TP_ARGS(ip, offset, count, flags, irec), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-               __field(loff_t, size) \
-               __field(loff_t, new_size) \
-               __field(loff_t, offset) \
-               __field(size_t, count) \
-               __field(int, flags) \
-               __field(xfs_fileoff_t, startoff) \
-               __field(xfs_fsblock_t, startblock) \
-               __field(xfs_filblks_t, blockcount) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = VFS_I(ip)->i_sb->s_dev; \
-               __entry->ino = ip->i_ino; \
-               __entry->size = ip->i_d.di_size; \
-               __entry->new_size = ip->i_new_size; \
-               __entry->offset = offset; \
-               __entry->count = count; \
-               __entry->flags = flags; \
-               __entry->startoff = irec ? irec->br_startoff : 0; \
-               __entry->startblock = irec ? irec->br_startblock : 0; \
-               __entry->blockcount = irec ? irec->br_blockcount : 0; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
-                 "offset 0x%llx count %zd flags %s " \
-                 "startoff 0x%llx startblock %lld blockcount 0x%llx", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->ino, \
-                 __entry->size, \
-                 __entry->new_size, \
-                 __entry->offset, \
-                 __entry->count, \
-                 __print_flags(__entry->flags, "|", BMAPI_FLAGS), \
-                 __entry->startoff, \
-                 (__int64_t)__entry->startblock, \
-                 __entry->blockcount) \
+DECLARE_EVENT_CLASS(xfs_iomap_class,
+       TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count,
+                int flags, struct xfs_bmbt_irec *irec),
+       TP_ARGS(ip, offset, count, flags, irec),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(loff_t, size)
+               __field(loff_t, new_size)
+               __field(loff_t, offset)
+               __field(size_t, count)
+               __field(int, flags)
+               __field(xfs_fileoff_t, startoff)
+               __field(xfs_fsblock_t, startblock)
+               __field(xfs_filblks_t, blockcount)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->size = ip->i_d.di_size;
+               __entry->new_size = ip->i_new_size;
+               __entry->offset = offset;
+               __entry->count = count;
+               __entry->flags = flags;
+               __entry->startoff = irec ? irec->br_startoff : 0;
+               __entry->startblock = irec ? irec->br_startblock : 0;
+               __entry->blockcount = irec ? irec->br_blockcount : 0;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
+                 "offset 0x%llx count %zd flags %s "
+                 "startoff 0x%llx startblock %lld blockcount 0x%llx",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->size,
+                 __entry->new_size,
+                 __entry->offset,
+                 __entry->count,
+                 __print_flags(__entry->flags, "|", BMAPI_FLAGS),
+                 __entry->startoff,
+                 (__int64_t)__entry->startblock,
+                 __entry->blockcount)
 )
+
+#define DEFINE_IOMAP_EVENT(name)       \
+DEFINE_EVENT(xfs_iomap_class, name,    \
+       TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count, \
+                int flags, struct xfs_bmbt_irec *irec),                \
+       TP_ARGS(ip, offset, count, flags, irec))
 DEFINE_IOMAP_EVENT(xfs_iomap_enter);
 DEFINE_IOMAP_EVENT(xfs_iomap_found);
 DEFINE_IOMAP_EVENT(xfs_iomap_alloc);
 
-#define DEFINE_SIMPLE_IO_EVENT(name) \
-TRACE_EVENT(name, \
-       TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count), \
-       TP_ARGS(ip, offset, count), \
-       TP_STRUCT__entry( \
-               __field(dev_t, dev) \
-               __field(xfs_ino_t, ino) \
-               __field(loff_t, size) \
-               __field(loff_t, new_size) \
-               __field(loff_t, offset) \
-               __field(size_t, count) \
-       ), \
-       TP_fast_assign( \
-               __entry->dev = VFS_I(ip)->i_sb->s_dev; \
-               __entry->ino = ip->i_ino; \
-               __entry->size = ip->i_d.di_size; \
-               __entry->new_size = ip->i_new_size; \
-               __entry->offset = offset; \
-               __entry->count = count; \
-       ), \
-       TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
-                 "offset 0x%llx count %zd", \
-                 MAJOR(__entry->dev), MINOR(__entry->dev), \
-                 __entry->ino, \
-                 __entry->size, \
-                 __entry->new_size, \
-                 __entry->offset, \
-                 __entry->count) \
+DECLARE_EVENT_CLASS(xfs_simple_io_class,
+       TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count),
+       TP_ARGS(ip, offset, count),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(loff_t, size)
+               __field(loff_t, new_size)
+               __field(loff_t, offset)
+               __field(size_t, count)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->size = ip->i_d.di_size;
+               __entry->new_size = ip->i_new_size;
+               __entry->offset = offset;
+               __entry->count = count;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
+                 "offset 0x%llx count %zd",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->size,
+                 __entry->new_size,
+                 __entry->offset,
+                 __entry->count)
 );
+
+#define DEFINE_SIMPLE_IO_EVENT(name)   \
+DEFINE_EVENT(xfs_simple_io_class, name,        \
+       TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count),        \
+       TP_ARGS(ip, offset, count))
 DEFINE_SIMPLE_IO_EVENT(xfs_delalloc_enospc);
 DEFINE_SIMPLE_IO_EVENT(xfs_unwritten_convert);
 
index 38e7641466442183ff55173ecf71eb3de6ba3bbd..8c117ff2e3ab00d8939f7ec596063988faae283f 100644 (file)
@@ -249,8 +249,10 @@ xfs_qm_hold_quotafs_ref(
 
        if (!xfs_Gqm) {
                xfs_Gqm = xfs_Gqm_init();
-               if (!xfs_Gqm)
+               if (!xfs_Gqm) {
+                       mutex_unlock(&xfs_Gqm_lock);
                        return ENOMEM;
+               }
        }
 
        /*
@@ -1630,10 +1632,7 @@ xfs_qm_dqusage_adjust(
        xfs_ino_t       ino,            /* inode number to get data for */
        void            __user *buffer, /* not used */
        int             ubsize,         /* not used */
-       void            *private_data,  /* not used */
-       xfs_daddr_t     bno,            /* starting block of inode cluster */
        int             *ubused,        /* not used */
-       void            *dip,           /* on-disk inode pointer (not used) */
        int             *res)           /* result code value */
 {
        xfs_inode_t     *ip;
@@ -1658,7 +1657,7 @@ xfs_qm_dqusage_adjust(
         * the case in all other instances. It's OK that we do this because
         * quotacheck is done only at mount time.
         */
-       if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip, bno))) {
+       if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip))) {
                *res = BULKSTAT_RV_NOTHING;
                return error;
        }
@@ -1794,12 +1793,13 @@ xfs_qm_quotacheck(
                 * Iterate thru all the inodes in the file system,
                 * adjusting the corresponding dquot counters in core.
                 */
-               if ((error = xfs_bulkstat(mp, &lastino, &count,
-                                    xfs_qm_dqusage_adjust, NULL,
-                                    structsz, NULL, BULKSTAT_FG_IGET, &done)))
+               error = xfs_bulkstat(mp, &lastino, &count,
+                                    xfs_qm_dqusage_adjust,
+                                    structsz, NULL, &done);
+               if (error)
                        break;
 
-       } while (! done);
+       } while (!done);
 
        /*
         * We've made all the changes that we need to make incore.
@@ -1887,14 +1887,14 @@ xfs_qm_init_quotainos(
                    mp->m_sb.sb_uquotino != NULLFSINO) {
                        ASSERT(mp->m_sb.sb_uquotino > 0);
                        if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
-                                            0, 0, &uip, 0)))
+                                            0, 0, &uip)))
                                return XFS_ERROR(error);
                }
                if (XFS_IS_OQUOTA_ON(mp) &&
                    mp->m_sb.sb_gquotino != NULLFSINO) {
                        ASSERT(mp->m_sb.sb_gquotino > 0);
                        if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
-                                            0, 0, &gip, 0))) {
+                                            0, 0, &gip))) {
                                if (uip)
                                        IRELE(uip);
                                return XFS_ERROR(error);
index 92b002f1805fdc85c237ea295728a6bc44dd8986..b4487764e923b7c493aac813e9161764a0f0ccfb 100644 (file)
@@ -262,7 +262,7 @@ xfs_qm_scall_trunc_qfiles(
        }
 
        if ((flags & XFS_DQ_USER) && mp->m_sb.sb_uquotino != NULLFSINO) {
-               error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip, 0);
+               error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip);
                if (!error) {
                        error = xfs_truncate_file(mp, qip);
                        IRELE(qip);
@@ -271,7 +271,7 @@ xfs_qm_scall_trunc_qfiles(
 
        if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
            mp->m_sb.sb_gquotino != NULLFSINO) {
-               error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
+               error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip);
                if (!error2) {
                        error2 = xfs_truncate_file(mp, qip);
                        IRELE(qip);
@@ -417,12 +417,12 @@ xfs_qm_scall_getqstat(
        }
        if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
                if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
-                                       0, 0, &uip, 0) == 0)
+                                       0, 0, &uip) == 0)
                        tempuqip = B_TRUE;
        }
        if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
                if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
-                                       0, 0, &gip, 0) == 0)
+                                       0, 0, &gip) == 0)
                        tempgqip = B_TRUE;
        }
        if (uip) {
@@ -1109,10 +1109,7 @@ xfs_qm_internalqcheck_adjust(
        xfs_ino_t       ino,            /* inode number to get data for */
        void            __user *buffer, /* not used */
        int             ubsize,         /* not used */
-       void            *private_data,  /* not used */
-       xfs_daddr_t     bno,            /* starting block of inode cluster */
        int             *ubused,        /* not used */
-       void            *dip,           /* not used */
        int             *res)           /* bulkstat result code */
 {
        xfs_inode_t             *ip;
@@ -1134,7 +1131,7 @@ xfs_qm_internalqcheck_adjust(
        ipreleased = B_FALSE;
  again:
        lock_flags = XFS_ILOCK_SHARED;
-       if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip, bno))) {
+       if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip))) {
                *res = BULKSTAT_RV_NOTHING;
                return (error);
        }
@@ -1205,15 +1202,15 @@ xfs_qm_internalqcheck(
                 * Iterate thru all the inodes in the file system,
                 * adjusting the corresponding dquot counters
                 */
-               if ((error = xfs_bulkstat(mp, &lastino, &count,
-                                xfs_qm_internalqcheck_adjust, NULL,
-                                0, NULL, BULKSTAT_FG_IGET, &done))) {
+               error = xfs_bulkstat(mp, &lastino, &count,
+                                xfs_qm_internalqcheck_adjust,
+                                0, NULL, &done);
+               if (error) {
+                       cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);
                        break;
                }
-       } while (! done);
-       if (error) {
-               cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);
-       }
+       } while (!done);
+
        cmn_err(CE_DEBUG, "Checking results against system dquots");
        for (i = 0; i < qmtest_hashmask; i++) {
                xfs_dqtest_t    *d, *n;
index 401f364ad36ce52022cabf6ccafa9d58de39dcd2..4917d4eed4edaeac56edffc1d65e4b7bc92acaa7 100644 (file)
@@ -227,7 +227,6 @@ typedef struct xfs_perag {
 
        atomic_t        pagf_fstrms;    /* # of filestreams active in this AG */
 
-       int             pag_ici_init;   /* incore inode cache initialised */
        rwlock_t        pag_ici_lock;   /* incore inode lock */
        struct radix_tree_root pag_ici_root;    /* incore inode cache root */
        int             pag_ici_reclaimable;    /* reclaimable inodes */
index 5bba29a07812cb761a9094e2ca1448491e99fc27..7f159d2a429a97e8a71e0fd57298ec499519c064 100644 (file)
@@ -69,7 +69,9 @@ xfs_swapext(
                goto out;
        }
 
-       if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) {
+       if (!(file->f_mode & FMODE_WRITE) ||
+           !(file->f_mode & FMODE_READ) ||
+           (file->f_flags & O_APPEND)) {
                error = XFS_ERROR(EBADF);
                goto out_put_file;
        }
@@ -81,6 +83,7 @@ xfs_swapext(
        }
 
        if (!(tmp_file->f_mode & FMODE_WRITE) ||
+           !(tmp_file->f_mode & FMODE_READ) ||
            (tmp_file->f_flags & O_APPEND)) {
                error = XFS_ERROR(EBADF);
                goto out_put_tmp_file;
index 9d884c127bb980c9c24b934113be222a4fc1093d..c7142a064c48d7b052d9ac0225f33562d0552386 100644 (file)
@@ -1203,6 +1203,63 @@ error0:
        return error;
 }
 
+STATIC int
+xfs_imap_lookup(
+       struct xfs_mount        *mp,
+       struct xfs_trans        *tp,
+       xfs_agnumber_t          agno,
+       xfs_agino_t             agino,
+       xfs_agblock_t           agbno,
+       xfs_agblock_t           *chunk_agbno,
+       xfs_agblock_t           *offset_agbno,
+       int                     flags)
+{
+       struct xfs_inobt_rec_incore rec;
+       struct xfs_btree_cur    *cur;
+       struct xfs_buf          *agbp;
+       xfs_agino_t             startino;
+       int                     error;
+       int                     i;
+
+       error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
+       if (error) {
+               xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
+                               "xfs_ialloc_read_agi() returned "
+                               "error %d, agno %d",
+                               error, agno);
+               return error;
+       }
+
+       /*
+        * derive and lookup the exact inode record for the given agino. If the
+        * record cannot be found, then it's an invalid inode number and we
+        * should abort.
+        */
+       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
+       startino = agino & ~(XFS_IALLOC_INODES(mp) - 1);
+       error = xfs_inobt_lookup(cur, startino, XFS_LOOKUP_EQ, &i);
+       if (!error) {
+               if (i)
+                       error = xfs_inobt_get_rec(cur, &rec, &i);
+               if (!error && i == 0)
+                       error = EINVAL;
+       }
+
+       xfs_trans_brelse(tp, agbp);
+       xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
+       if (error)
+               return error;
+
+       /* for untrusted inodes check it is allocated first */
+       if ((flags & XFS_IGET_UNTRUSTED) &&
+           (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino)))
+               return EINVAL;
+
+       *chunk_agbno = XFS_AGINO_TO_AGBNO(mp, rec.ir_startino);
+       *offset_agbno = agbno - *chunk_agbno;
+       return 0;
+}
+
 /*
  * Return the location of the inode in imap, for mapping it into a buffer.
  */
@@ -1235,8 +1292,11 @@ xfs_imap(
        if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
            ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
 #ifdef DEBUG
-               /* no diagnostics for bulkstat, ino comes from userspace */
-               if (flags & XFS_IGET_BULKSTAT)
+               /*
+                * Don't output diagnostic information for untrusted inodes
+                * as they can be invalid without implying corruption.
+                */
+               if (flags & XFS_IGET_UNTRUSTED)
                        return XFS_ERROR(EINVAL);
                if (agno >= mp->m_sb.sb_agcount) {
                        xfs_fs_cmn_err(CE_ALERT, mp,
@@ -1263,6 +1323,23 @@ xfs_imap(
                return XFS_ERROR(EINVAL);
        }
 
+       blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
+
+       /*
+        * For bulkstat and handle lookups, we have an untrusted inode number
+        * that we have to verify is valid. We cannot do this just by reading
+        * the inode buffer as it may have been unlinked and removed leaving
+        * inodes in stale state on disk. Hence we have to do a btree lookup
+        * in all cases where an untrusted inode number is passed.
+        */
+       if (flags & XFS_IGET_UNTRUSTED) {
+               error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
+                                       &chunk_agbno, &offset_agbno, flags);
+               if (error)
+                       return error;
+               goto out_map;
+       }
+
        /*
         * If the inode cluster size is the same as the blocksize or
         * smaller we get to the buffer by simple arithmetics.
@@ -1277,24 +1354,6 @@ xfs_imap(
                return 0;
        }
 
-       blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
-
-       /*
-        * If we get a block number passed from bulkstat we can use it to
-        * find the buffer easily.
-        */
-       if (imap->im_blkno) {
-               offset = XFS_INO_TO_OFFSET(mp, ino);
-               ASSERT(offset < mp->m_sb.sb_inopblock);
-
-               cluster_agbno = xfs_daddr_to_agbno(mp, imap->im_blkno);
-               offset += (agbno - cluster_agbno) * mp->m_sb.sb_inopblock;
-
-               imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster);
-               imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog);
-               return 0;
-       }
-
        /*
         * If the inode chunks are aligned then use simple maths to
         * find the location. Otherwise we have to do a btree
@@ -1304,50 +1363,13 @@ xfs_imap(
                offset_agbno = agbno & mp->m_inoalign_mask;
                chunk_agbno = agbno - offset_agbno;
        } else {
-               xfs_btree_cur_t *cur;   /* inode btree cursor */
-               xfs_inobt_rec_incore_t chunk_rec;
-               xfs_buf_t       *agbp;  /* agi buffer */
-               int             i;      /* temp state */
-
-               error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
-               if (error) {
-                       xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-                                       "xfs_ialloc_read_agi() returned "
-                                       "error %d, agno %d",
-                                       error, agno);
-                       return error;
-               }
-
-               cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
-               error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i);
-               if (error) {
-                       xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-                                       "xfs_inobt_lookup() failed");
-                       goto error0;
-               }
-
-               error = xfs_inobt_get_rec(cur, &chunk_rec, &i);
-               if (error) {
-                       xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-                                       "xfs_inobt_get_rec() failed");
-                       goto error0;
-               }
-               if (i == 0) {
-#ifdef DEBUG
-                       xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-                                       "xfs_inobt_get_rec() failed");
-#endif /* DEBUG */
-                       error = XFS_ERROR(EINVAL);
-               }
- error0:
-               xfs_trans_brelse(tp, agbp);
-               xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
+               error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
+                                       &chunk_agbno, &offset_agbno, flags);
                if (error)
                        return error;
-               chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_rec.ir_startino);
-               offset_agbno = agbno - chunk_agbno;
        }
 
+out_map:
        ASSERT(agbno >= chunk_agbno);
        cluster_agbno = chunk_agbno +
                ((offset_agbno / blks_per_cluster) * blks_per_cluster);
index 6845db90818f2223cf9fdbc735ed8a423b9338bc..8f8b91be2c996dce5b75901038c507bb4b9ef1da 100644 (file)
@@ -259,7 +259,6 @@ xfs_iget_cache_miss(
        xfs_trans_t             *tp,
        xfs_ino_t               ino,
        struct xfs_inode        **ipp,
-       xfs_daddr_t             bno,
        int                     flags,
        int                     lock_flags)
 {
@@ -272,7 +271,7 @@ xfs_iget_cache_miss(
        if (!ip)
                return ENOMEM;
 
-       error = xfs_iread(mp, tp, ip, bno, flags);
+       error = xfs_iread(mp, tp, ip, flags);
        if (error)
                goto out_destroy;
 
@@ -358,8 +357,6 @@ out_destroy:
  *        within the file system for the inode being requested.
  * lock_flags -- flags indicating how to lock the inode.  See the comment
  *              for xfs_ilock() for a list of valid values.
- * bno -- the block number starting the buffer containing the inode,
- *       if known (as by bulkstat), else 0.
  */
 int
 xfs_iget(
@@ -368,8 +365,7 @@ xfs_iget(
        xfs_ino_t       ino,
        uint            flags,
        uint            lock_flags,
-       xfs_inode_t     **ipp,
-       xfs_daddr_t     bno)
+       xfs_inode_t     **ipp)
 {
        xfs_inode_t     *ip;
        int             error;
@@ -382,9 +378,6 @@ xfs_iget(
 
        /* get the perag structure and ensure that it's inode capable */
        pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
-       if (!pag->pagi_inodeok)
-               return EINVAL;
-       ASSERT(pag->pag_ici_init);
        agino = XFS_INO_TO_AGINO(mp, ino);
 
 again:
@@ -400,7 +393,7 @@ again:
                read_unlock(&pag->pag_ici_lock);
                XFS_STATS_INC(xs_ig_missed);
 
-               error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip, bno,
+               error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip,
                                                        flags, lock_flags);
                if (error)
                        goto out_error_or_again;
@@ -744,30 +737,24 @@ xfs_ilock_demote(
 }
 
 #ifdef DEBUG
-/*
- * Debug-only routine, without additional rw_semaphore APIs, we can
- * now only answer requests regarding whether we hold the lock for write
- * (reader state is outside our visibility, we only track writer state).
- *
- * Note: this means !xfs_isilocked would give false positives, so don't do that.
- */
 int
 xfs_isilocked(
        xfs_inode_t             *ip,
        uint                    lock_flags)
 {
-       if ((lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) ==
-                       XFS_ILOCK_EXCL) {
-               if (!ip->i_lock.mr_writer)
-                       return 0;
+       if (lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) {
+               if (!(lock_flags & XFS_ILOCK_SHARED))
+                       return !!ip->i_lock.mr_writer;
+               return rwsem_is_locked(&ip->i_lock.mr_lock);
        }
 
-       if ((lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) ==
-                       XFS_IOLOCK_EXCL) {
-               if (!ip->i_iolock.mr_writer)
-                       return 0;
+       if (lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) {
+               if (!(lock_flags & XFS_IOLOCK_SHARED))
+                       return !!ip->i_iolock.mr_writer;
+               return rwsem_is_locked(&ip->i_iolock.mr_lock);
        }
 
-       return 1;
+       ASSERT(0);
+       return 0;
 }
 #endif
index 8cd6e8d8fe9c452e1d7c995d216a4f5745c61f53..b76a829d7e200d4ead1b9e4406faf93f1e4093e0 100644 (file)
@@ -177,7 +177,7 @@ xfs_imap_to_bp(
                if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
                                                XFS_ERRTAG_ITOBP_INOTOBP,
                                                XFS_RANDOM_ITOBP_INOTOBP))) {
-                       if (iget_flags & XFS_IGET_BULKSTAT) {
+                       if (iget_flags & XFS_IGET_UNTRUSTED) {
                                xfs_trans_brelse(tp, bp);
                                return XFS_ERROR(EINVAL);
                        }
@@ -787,7 +787,6 @@ xfs_iread(
        xfs_mount_t     *mp,
        xfs_trans_t     *tp,
        xfs_inode_t     *ip,
-       xfs_daddr_t     bno,
        uint            iget_flags)
 {
        xfs_buf_t       *bp;
@@ -797,11 +796,9 @@ xfs_iread(
        /*
         * Fill in the location information in the in-core inode.
         */
-       ip->i_imap.im_blkno = bno;
        error = xfs_imap(mp, tp, ip->i_ino, &ip->i_imap, iget_flags);
        if (error)
                return error;
-       ASSERT(bno == 0 || bno == ip->i_imap.im_blkno);
 
        /*
         * Get pointers to the on-disk inode and the buffer containing it.
@@ -1940,10 +1937,10 @@ xfs_ifree_cluster(
        int                     blks_per_cluster;
        int                     nbufs;
        int                     ninodes;
-       int                     i, j, found, pre_flushed;
+       int                     i, j;
        xfs_daddr_t             blkno;
        xfs_buf_t               *bp;
-       xfs_inode_t             *ip, **ip_found;
+       xfs_inode_t             *ip;
        xfs_inode_log_item_t    *iip;
        xfs_log_item_t          *lip;
        struct xfs_perag        *pag;
@@ -1960,114 +1957,97 @@ xfs_ifree_cluster(
                nbufs = XFS_IALLOC_BLOCKS(mp) / blks_per_cluster;
        }
 
-       ip_found = kmem_alloc(ninodes * sizeof(xfs_inode_t *), KM_NOFS);
-
        for (j = 0; j < nbufs; j++, inum += ninodes) {
+               int     found = 0;
+
                blkno = XFS_AGB_TO_DADDR(mp, XFS_INO_TO_AGNO(mp, inum),
                                         XFS_INO_TO_AGBNO(mp, inum));
 
+               /*
+                * We obtain and lock the backing buffer first in the process
+                * here, as we have to ensure that any dirty inode that we
+                * can't get the flush lock on is attached to the buffer.
+                * If we scan the in-memory inodes first, then buffer IO can
+                * complete before we get a lock on it, and hence we may fail
+                * to mark all the active inodes on the buffer stale.
+                */
+               bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
+                                       mp->m_bsize * blks_per_cluster,
+                                       XBF_LOCK);
+
+               /*
+                * Walk the inodes already attached to the buffer and mark them
+                * stale. These will all have the flush locks held, so an
+                * in-memory inode walk can't lock them.
+                */
+               lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
+               while (lip) {
+                       if (lip->li_type == XFS_LI_INODE) {
+                               iip = (xfs_inode_log_item_t *)lip;
+                               ASSERT(iip->ili_logged == 1);
+                               lip->li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_istale_done;
+                               xfs_trans_ail_copy_lsn(mp->m_ail,
+                                                       &iip->ili_flush_lsn,
+                                                       &iip->ili_item.li_lsn);
+                               xfs_iflags_set(iip->ili_inode, XFS_ISTALE);
+                               found++;
+                       }
+                       lip = lip->li_bio_list;
+               }
 
                /*
-                * Look for each inode in memory and attempt to lock it,
-                * we can be racing with flush and tail pushing here.
-                * any inode we get the locks on, add to an array of
-                * inode items to process later.
+                * For each inode in memory attempt to add it to the inode
+                * buffer and set it up for being staled on buffer IO
+                * completion.  This is safe as we've locked out tail pushing
+                * and flushing by locking the buffer.
                 *
-                * The get the buffer lock, we could beat a flush
-                * or tail pushing thread to the lock here, in which
-                * case they will go looking for the inode buffer
-                * and fail, we need some other form of interlock
-                * here.
+                * We have already marked every inode that was part of a
+                * transaction stale above, which means there is no point in
+                * even trying to lock them.
                 */
-               found = 0;
                for (i = 0; i < ninodes; i++) {
                        read_lock(&pag->pag_ici_lock);
                        ip = radix_tree_lookup(&pag->pag_ici_root,
                                        XFS_INO_TO_AGINO(mp, (inum + i)));
 
-                       /* Inode not in memory or we found it already,
-                        * nothing to do
-                        */
+                       /* Inode not in memory or stale, nothing to do */
                        if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) {
                                read_unlock(&pag->pag_ici_lock);
                                continue;
                        }
 
-                       if (xfs_inode_clean(ip)) {
-                               read_unlock(&pag->pag_ici_lock);
-                               continue;
-                       }
-
-                       /* If we can get the locks then add it to the
-                        * list, otherwise by the time we get the bp lock
-                        * below it will already be attached to the
-                        * inode buffer.
-                        */
-
-                       /* This inode will already be locked - by us, lets
-                        * keep it that way.
-                        */
-
-                       if (ip == free_ip) {
-                               if (xfs_iflock_nowait(ip)) {
-                                       xfs_iflags_set(ip, XFS_ISTALE);
-                                       if (xfs_inode_clean(ip)) {
-                                               xfs_ifunlock(ip);
-                                       } else {
-                                               ip_found[found++] = ip;
-                                       }
-                               }
+                       /* don't try to lock/unlock the current inode */
+                       if (ip != free_ip &&
+                           !xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
                                read_unlock(&pag->pag_ici_lock);
                                continue;
                        }
+                       read_unlock(&pag->pag_ici_lock);
 
-                       if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
-                               if (xfs_iflock_nowait(ip)) {
-                                       xfs_iflags_set(ip, XFS_ISTALE);
-
-                                       if (xfs_inode_clean(ip)) {
-                                               xfs_ifunlock(ip);
-                                               xfs_iunlock(ip, XFS_ILOCK_EXCL);
-                                       } else {
-                                               ip_found[found++] = ip;
-                                       }
-                               } else {
+                       if (!xfs_iflock_nowait(ip)) {
+                               if (ip != free_ip)
                                        xfs_iunlock(ip, XFS_ILOCK_EXCL);
-                               }
+                               continue;
                        }
-                       read_unlock(&pag->pag_ici_lock);
-               }
 
-               bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno, 
-                                       mp->m_bsize * blks_per_cluster,
-                                       XBF_LOCK);
-
-               pre_flushed = 0;
-               lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
-               while (lip) {
-                       if (lip->li_type == XFS_LI_INODE) {
-                               iip = (xfs_inode_log_item_t *)lip;
-                               ASSERT(iip->ili_logged == 1);
-                               lip->li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_istale_done;
-                               xfs_trans_ail_copy_lsn(mp->m_ail,
-                                                       &iip->ili_flush_lsn,
-                                                       &iip->ili_item.li_lsn);
-                               xfs_iflags_set(iip->ili_inode, XFS_ISTALE);
-                               pre_flushed++;
+                       xfs_iflags_set(ip, XFS_ISTALE);
+                       if (xfs_inode_clean(ip)) {
+                               ASSERT(ip != free_ip);
+                               xfs_ifunlock(ip);
+                               xfs_iunlock(ip, XFS_ILOCK_EXCL);
+                               continue;
                        }
-                       lip = lip->li_bio_list;
-               }
 
-               for (i = 0; i < found; i++) {
-                       ip = ip_found[i];
                        iip = ip->i_itemp;
-
                        if (!iip) {
+                               /* inode with unlogged changes only */
+                               ASSERT(ip != free_ip);
                                ip->i_update_core = 0;
                                xfs_ifunlock(ip);
                                xfs_iunlock(ip, XFS_ILOCK_EXCL);
                                continue;
                        }
+                       found++;
 
                        iip->ili_last_fields = iip->ili_format.ilf_fields;
                        iip->ili_format.ilf_fields = 0;
@@ -2078,17 +2058,16 @@ xfs_ifree_cluster(
                        xfs_buf_attach_iodone(bp,
                                (void(*)(xfs_buf_t*,xfs_log_item_t*))
                                xfs_istale_done, (xfs_log_item_t *)iip);
-                       if (ip != free_ip) {
+
+                       if (ip != free_ip)
                                xfs_iunlock(ip, XFS_ILOCK_EXCL);
-                       }
                }
 
-               if (found || pre_flushed)
+               if (found)
                        xfs_trans_stale_inode_buf(tp, bp);
                xfs_trans_binval(tp, bp);
        }
 
-       kmem_free(ip_found);
        xfs_perag_put(pag);
 }
 
@@ -2649,8 +2628,6 @@ xfs_iflush_cluster(
        int                     i;
 
        pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
-       ASSERT(pag->pagi_inodeok);
-       ASSERT(pag->pag_ici_init);
 
        inodes_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog;
        ilist_size = inodes_per_cluster * sizeof(xfs_inode_t *);
index 9965e40a4615d8c09001ffe800c7e750ab8bece7..78550df13cd664ee4811447f836e9d0f8dc31405 100644 (file)
@@ -442,7 +442,7 @@ static inline void xfs_ifunlock(xfs_inode_t *ip)
  * xfs_iget.c prototypes.
  */
 int            xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
-                        uint, uint, xfs_inode_t **, xfs_daddr_t);
+                        uint, uint, xfs_inode_t **);
 void           xfs_iput(xfs_inode_t *, uint);
 void           xfs_iput_new(xfs_inode_t *, uint);
 void           xfs_ilock(xfs_inode_t *, uint);
@@ -500,7 +500,7 @@ do { \
  * Flags for xfs_iget()
  */
 #define XFS_IGET_CREATE                0x1
-#define XFS_IGET_BULKSTAT      0x2
+#define XFS_IGET_UNTRUSTED     0x2
 
 int            xfs_inotobp(struct xfs_mount *, struct xfs_trans *,
                            xfs_ino_t, struct xfs_dinode **,
@@ -509,7 +509,7 @@ int         xfs_itobp(struct xfs_mount *, struct xfs_trans *,
                          struct xfs_inode *, struct xfs_dinode **,
                          struct xfs_buf **, uint);
 int            xfs_iread(struct xfs_mount *, struct xfs_trans *,
-                         struct xfs_inode *, xfs_daddr_t, uint);
+                         struct xfs_inode *, uint);
 void           xfs_dinode_to_disk(struct xfs_dinode *,
                                   struct xfs_icdinode *);
 void           xfs_idestroy_fork(struct xfs_inode *, int);
index b1b801e4a28e41643d93b6c5438e01718c665bed..2b86f86105125c3869a641b68bc73b984ce69e79 100644 (file)
@@ -49,24 +49,40 @@ xfs_internal_inum(
                 (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino)));
 }
 
-STATIC int
-xfs_bulkstat_one_iget(
-       xfs_mount_t     *mp,            /* mount point for filesystem */
-       xfs_ino_t       ino,            /* inode number to get data for */
-       xfs_daddr_t     bno,            /* starting bno of inode cluster */
-       xfs_bstat_t     *buf,           /* return buffer */
-       int             *stat)          /* BULKSTAT_RV_... */
+/*
+ * Return stat information for one inode.
+ * Return 0 if ok, else errno.
+ */
+int
+xfs_bulkstat_one_int(
+       struct xfs_mount        *mp,            /* mount point for filesystem */
+       xfs_ino_t               ino,            /* inode to get data for */
+       void __user             *buffer,        /* buffer to place output in */
+       int                     ubsize,         /* size of buffer */
+       bulkstat_one_fmt_pf     formatter,      /* formatter, copy to user */
+       int                     *ubused,        /* bytes used by me */
+       int                     *stat)          /* BULKSTAT_RV_... */
 {
-       xfs_icdinode_t  *dic;   /* dinode core info pointer */
-       xfs_inode_t     *ip;            /* incore inode pointer */
-       struct inode    *inode;
-       int             error;
+       struct xfs_icdinode     *dic;           /* dinode core info pointer */
+       struct xfs_inode        *ip;            /* incore inode pointer */
+       struct inode            *inode;
+       struct xfs_bstat        *buf;           /* return buffer */
+       int                     error = 0;      /* error value */
+
+       *stat = BULKSTAT_RV_NOTHING;
+
+       if (!buffer || xfs_internal_inum(mp, ino))
+               return XFS_ERROR(EINVAL);
+
+       buf = kmem_alloc(sizeof(*buf), KM_SLEEP | KM_MAYFAIL);
+       if (!buf)
+               return XFS_ERROR(ENOMEM);
 
        error = xfs_iget(mp, NULL, ino,
-                        XFS_IGET_BULKSTAT, XFS_ILOCK_SHARED, &ip, bno);
+                        XFS_IGET_UNTRUSTED, XFS_ILOCK_SHARED, &ip);
        if (error) {
                *stat = BULKSTAT_RV_NOTHING;
-               return error;
+               goto out_free;
        }
 
        ASSERT(ip != NULL);
@@ -127,77 +143,16 @@ xfs_bulkstat_one_iget(
                buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks;
                break;
        }
-
        xfs_iput(ip, XFS_ILOCK_SHARED);
-       return error;
-}
 
-STATIC void
-xfs_bulkstat_one_dinode(
-       xfs_mount_t     *mp,            /* mount point for filesystem */
-       xfs_ino_t       ino,            /* inode number to get data for */
-       xfs_dinode_t    *dic,           /* dinode inode pointer */
-       xfs_bstat_t     *buf)           /* return buffer */
-{
-       /*
-        * The inode format changed when we moved the link count and
-        * made it 32 bits long.  If this is an old format inode,
-        * convert it in memory to look like a new one.  If it gets
-        * flushed to disk we will convert back before flushing or
-        * logging it.  We zero out the new projid field and the old link
-        * count field.  We'll handle clearing the pad field (the remains
-        * of the old uuid field) when we actually convert the inode to
-        * the new format. We don't change the version number so that we
-        * can distinguish this from a real new format inode.
-        */
-       if (dic->di_version == 1) {
-               buf->bs_nlink = be16_to_cpu(dic->di_onlink);
-               buf->bs_projid = 0;
-       } else {
-               buf->bs_nlink = be32_to_cpu(dic->di_nlink);
-               buf->bs_projid = be16_to_cpu(dic->di_projid);
-       }
+       error = formatter(buffer, ubsize, ubused, buf);
 
-       buf->bs_ino = ino;
-       buf->bs_mode = be16_to_cpu(dic->di_mode);
-       buf->bs_uid = be32_to_cpu(dic->di_uid);
-       buf->bs_gid = be32_to_cpu(dic->di_gid);
-       buf->bs_size = be64_to_cpu(dic->di_size);
-       buf->bs_atime.tv_sec = be32_to_cpu(dic->di_atime.t_sec);
-       buf->bs_atime.tv_nsec = be32_to_cpu(dic->di_atime.t_nsec);
-       buf->bs_mtime.tv_sec = be32_to_cpu(dic->di_mtime.t_sec);
-       buf->bs_mtime.tv_nsec = be32_to_cpu(dic->di_mtime.t_nsec);
-       buf->bs_ctime.tv_sec = be32_to_cpu(dic->di_ctime.t_sec);
-       buf->bs_ctime.tv_nsec = be32_to_cpu(dic->di_ctime.t_nsec);
-       buf->bs_xflags = xfs_dic2xflags(dic);
-       buf->bs_extsize = be32_to_cpu(dic->di_extsize) << mp->m_sb.sb_blocklog;
-       buf->bs_extents = be32_to_cpu(dic->di_nextents);
-       buf->bs_gen = be32_to_cpu(dic->di_gen);
-       memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
-       buf->bs_dmevmask = be32_to_cpu(dic->di_dmevmask);
-       buf->bs_dmstate = be16_to_cpu(dic->di_dmstate);
-       buf->bs_aextents = be16_to_cpu(dic->di_anextents);
-       buf->bs_forkoff = XFS_DFORK_BOFF(dic);
+       if (!error)
+               *stat = BULKSTAT_RV_DIDONE;
 
-       switch (dic->di_format) {
-       case XFS_DINODE_FMT_DEV:
-               buf->bs_rdev = xfs_dinode_get_rdev(dic);
-               buf->bs_blksize = BLKDEV_IOSIZE;
-               buf->bs_blocks = 0;
-               break;
-       case XFS_DINODE_FMT_LOCAL:
-       case XFS_DINODE_FMT_UUID:
-               buf->bs_rdev = 0;
-               buf->bs_blksize = mp->m_sb.sb_blocksize;
-               buf->bs_blocks = 0;
-               break;
-       case XFS_DINODE_FMT_EXTENTS:
-       case XFS_DINODE_FMT_BTREE:
-               buf->bs_rdev = 0;
-               buf->bs_blksize = mp->m_sb.sb_blocksize;
-               buf->bs_blocks = be64_to_cpu(dic->di_nblocks);
-               break;
-       }
+ out_free:
+       kmem_free(buf);
+       return error;
 }
 
 /* Return 0 on success or positive error */
@@ -217,118 +172,17 @@ xfs_bulkstat_one_fmt(
        return 0;
 }
 
-/*
- * Return stat information for one inode.
- * Return 0 if ok, else errno.
- */
-int                                    /* error status */
-xfs_bulkstat_one_int(
-       xfs_mount_t     *mp,            /* mount point for filesystem */
-       xfs_ino_t       ino,            /* inode number to get data for */
-       void            __user *buffer, /* buffer to place output in */
-       int             ubsize,         /* size of buffer */
-       bulkstat_one_fmt_pf formatter,  /* formatter, copy to user */
-       xfs_daddr_t     bno,            /* starting bno of inode cluster */
-       int             *ubused,        /* bytes used by me */
-       void            *dibuff,        /* on-disk inode buffer */
-       int             *stat)          /* BULKSTAT_RV_... */
-{
-       xfs_bstat_t     *buf;           /* return buffer */
-       int             error = 0;      /* error value */
-       xfs_dinode_t    *dip;           /* dinode inode pointer */
-
-       dip = (xfs_dinode_t *)dibuff;
-       *stat = BULKSTAT_RV_NOTHING;
-
-       if (!buffer || xfs_internal_inum(mp, ino))
-               return XFS_ERROR(EINVAL);
-
-       buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
-
-       if (dip == NULL) {
-               /* We're not being passed a pointer to a dinode.  This happens
-                * if BULKSTAT_FG_IGET is selected.  Do the iget.
-                */
-               error = xfs_bulkstat_one_iget(mp, ino, bno, buf, stat);
-               if (error)
-                       goto out_free;
-       } else {
-               xfs_bulkstat_one_dinode(mp, ino, dip, buf);
-       }
-
-       error = formatter(buffer, ubsize, ubused, buf);
-       if (error)
-               goto out_free;
-
-       *stat = BULKSTAT_RV_DIDONE;
-
- out_free:
-       kmem_free(buf);
-       return error;
-}
-
 int
 xfs_bulkstat_one(
        xfs_mount_t     *mp,            /* mount point for filesystem */
        xfs_ino_t       ino,            /* inode number to get data for */
        void            __user *buffer, /* buffer to place output in */
        int             ubsize,         /* size of buffer */
-       void            *private_data,  /* my private data */
-       xfs_daddr_t     bno,            /* starting bno of inode cluster */
        int             *ubused,        /* bytes used by me */
-       void            *dibuff,        /* on-disk inode buffer */
        int             *stat)          /* BULKSTAT_RV_... */
 {
        return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,
-                                   xfs_bulkstat_one_fmt, bno,
-                                   ubused, dibuff, stat);
-}
-
-/*
- * Test to see whether we can use the ondisk inode directly, based
- * on the given bulkstat flags, filling in dipp accordingly.
- * Returns zero if the inode is dodgey.
- */
-STATIC int
-xfs_bulkstat_use_dinode(
-       xfs_mount_t     *mp,
-       int             flags,
-       xfs_buf_t       *bp,
-       int             clustidx,
-       xfs_dinode_t    **dipp)
-{
-       xfs_dinode_t    *dip;
-       unsigned int    aformat;
-
-       *dipp = NULL;
-       if (!bp || (flags & BULKSTAT_FG_IGET))
-               return 1;
-       dip = (xfs_dinode_t *)
-                       xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog);
-       /*
-        * Check the buffer containing the on-disk inode for di_mode == 0.
-        * This is to prevent xfs_bulkstat from picking up just reclaimed
-        * inodes that have their in-core state initialized but not flushed
-        * to disk yet. This is a temporary hack that would require a proper
-        * fix in the future.
-        */
-       if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC ||
-           !XFS_DINODE_GOOD_VERSION(dip->di_version) ||
-           !dip->di_mode)
-               return 0;
-       if (flags & BULKSTAT_FG_QUICK) {
-               *dipp = dip;
-               return 1;
-       }
-       /* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */
-       aformat = dip->di_aformat;
-       if ((XFS_DFORK_Q(dip) == 0) ||
-           (aformat == XFS_DINODE_FMT_LOCAL) ||
-           (aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_anextents)) {
-               *dipp = dip;
-               return 1;
-       }
-       return 1;
+                                   xfs_bulkstat_one_fmt, ubused, stat);
 }
 
 #define XFS_BULKSTAT_UBLEFT(ubleft)    ((ubleft) >= statstruct_size)
@@ -342,10 +196,8 @@ xfs_bulkstat(
        xfs_ino_t               *lastinop, /* last inode returned */
        int                     *ubcountp, /* size of buffer/count returned */
        bulkstat_one_pf         formatter, /* func that'd fill a single buf */
-       void                    *private_data,/* private data for formatter */
        size_t                  statstruct_size, /* sizeof struct filling */
        char                    __user *ubuffer, /* buffer with inode stats */
-       int                     flags,  /* defined in xfs_itable.h */
        int                     *done)  /* 1 if there are more stats to get */
 {
        xfs_agblock_t           agbno=0;/* allocation group block number */
@@ -380,14 +232,12 @@ xfs_bulkstat(
        int                     ubelem; /* spaces used in user's buffer */
        int                     ubused; /* bytes used by formatter */
        xfs_buf_t               *bp;    /* ptr to on-disk inode cluster buf */
-       xfs_dinode_t            *dip;   /* ptr into bp for specific inode */
 
        /*
         * Get the last inode value, see if there's nothing to do.
         */
        ino = (xfs_ino_t)*lastinop;
        lastino = ino;
-       dip = NULL;
        agno = XFS_INO_TO_AGNO(mp, ino);
        agino = XFS_INO_TO_AGINO(mp, ino);
        if (agno >= mp->m_sb.sb_agcount ||
@@ -612,37 +462,6 @@ xfs_bulkstat(
                                                        irbp->ir_startino) +
                                                ((chunkidx & nimask) >>
                                                 mp->m_sb.sb_inopblog);
-
-                                       if (flags & (BULKSTAT_FG_QUICK |
-                                                    BULKSTAT_FG_INLINE)) {
-                                               int offset;
-
-                                               ino = XFS_AGINO_TO_INO(mp, agno,
-                                                                      agino);
-                                               bno = XFS_AGB_TO_DADDR(mp, agno,
-                                                                      agbno);
-
-                                               /*
-                                                * Get the inode cluster buffer
-                                                */
-                                               if (bp)
-                                                       xfs_buf_relse(bp);
-
-                                               error = xfs_inotobp(mp, NULL, ino, &dip,
-                                                                   &bp, &offset,
-                                                                   XFS_IGET_BULKSTAT);
-
-                                               if (!error)
-                                                       clustidx = offset / mp->m_sb.sb_inodesize;
-                                               if (XFS_TEST_ERROR(error != 0,
-                                                                  mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
-                                                                  XFS_RANDOM_BULKSTAT_READ_CHUNK)) {
-                                                       bp = NULL;
-                                                       ubleft = 0;
-                                                       rval = error;
-                                                       break;
-                                               }
-                                       }
                                }
                                ino = XFS_AGINO_TO_INO(mp, agno, agino);
                                bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
@@ -658,35 +477,13 @@ xfs_bulkstat(
                                 * when the chunk is used up.
                                 */
                                irbp->ir_freecount++;
-                               if (!xfs_bulkstat_use_dinode(mp, flags, bp,
-                                                            clustidx, &dip)) {
-                                       lastino = ino;
-                                       continue;
-                               }
-                               /*
-                                * If we need to do an iget, cannot hold bp.
-                                * Drop it, until starting the next cluster.
-                                */
-                               if ((flags & BULKSTAT_FG_INLINE) && !dip) {
-                                       if (bp)
-                                               xfs_buf_relse(bp);
-                                       bp = NULL;
-                               }
 
                                /*
                                 * Get the inode and fill in a single buffer.
-                                * BULKSTAT_FG_QUICK uses dip to fill it in.
-                                * BULKSTAT_FG_IGET uses igets.
-                                * BULKSTAT_FG_INLINE uses dip if we have an
-                                * inline attr fork, else igets.
-                                * See: xfs_bulkstat_one & xfs_dm_bulkstat_one.
-                                * This is also used to count inodes/blks, etc
-                                * in xfs_qm_quotacheck.
                                 */
                                ubused = statstruct_size;
-                               error = formatter(mp, ino, ubufp,
-                                               ubleft, private_data,
-                                               bno, &ubused, dip, &fmterror);
+                               error = formatter(mp, ino, ubufp, ubleft,
+                                                 &ubused, &fmterror);
                                if (fmterror == BULKSTAT_RV_NOTHING) {
                                        if (error && error != ENOENT &&
                                                error != EINVAL) {
@@ -778,8 +575,7 @@ xfs_bulkstat_single(
         */
 
        ino = (xfs_ino_t)*lastinop;
-       error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t),
-                                NULL, 0, NULL, NULL, &res);
+       error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t), 0, &res);
        if (error) {
                /*
                 * Special case way failed, do it the "long" way
@@ -788,8 +584,7 @@ xfs_bulkstat_single(
                (*lastinop)--;
                count = 1;
                if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one,
-                               NULL, sizeof(xfs_bstat_t), buffer,
-                               BULKSTAT_FG_IGET, done))
+                               sizeof(xfs_bstat_t), buffer, done))
                        return error;
                if (count == 0 || (xfs_ino_t)*lastinop != ino)
                        return error == EFSCORRUPTED ?
index 20792bf459468b84b6bb960d7328888a1ab35df8..97295d91d1703c21cbeacacc876f9eded07aeb38 100644 (file)
@@ -27,10 +27,7 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount      *mp,
                               xfs_ino_t        ino,
                               void             __user *buffer,
                               int              ubsize,
-                              void             *private_data,
-                              xfs_daddr_t      bno,
                               int              *ubused,
-                              void             *dip,
                               int              *stat);
 
 /*
@@ -40,13 +37,6 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount      *mp,
 #define BULKSTAT_RV_DIDONE     1
 #define BULKSTAT_RV_GIVEUP     2
 
-/*
- * Values for bulkstat flag argument.
- */
-#define BULKSTAT_FG_IGET       0x1     /* Go through the buffer cache */
-#define BULKSTAT_FG_QUICK      0x2     /* No iget, walk the dinode cluster */
-#define BULKSTAT_FG_INLINE     0x4     /* No iget if inline attrs */
-
 /*
  * Return stat information in bulk (by-inode) for the filesystem.
  */
@@ -56,10 +46,8 @@ xfs_bulkstat(
        xfs_ino_t       *lastino,       /* last inode returned */
        int             *count,         /* size of buffer/count returned */
        bulkstat_one_pf formatter,      /* func that'd fill a single buf */
-       void            *private_data,  /* private data for formatter */
        size_t          statstruct_size,/* sizeof struct that we're filling */
        char            __user *ubuffer,/* buffer with inode stats */
-       int             flags,          /* flag to control access method */
        int             *done);         /* 1 if there are more stats to get */
 
 int
@@ -82,9 +70,7 @@ xfs_bulkstat_one_int(
        void                    __user *buffer,
        int                     ubsize,
        bulkstat_one_fmt_pf     formatter,
-       xfs_daddr_t             bno,
        int                     *ubused,
-       void                    *dibuff,
        int                     *stat);
 
 int
@@ -93,10 +79,7 @@ xfs_bulkstat_one(
        xfs_ino_t               ino,
        void                    __user *buffer,
        int                     ubsize,
-       void                    *private_data,
-       xfs_daddr_t             bno,
        int                     *ubused,
-       void                    *dibuff,
        int                     *stat);
 
 typedef int (*inumbers_fmt_pf)(
index 14a69aec2c0b28c00d1824c7ae16fce497ff308c..9ac5cfab27b96da77ac033559229090a3c52490a 100644 (file)
@@ -132,15 +132,10 @@ xlog_align(
        int             nbblks,
        xfs_buf_t       *bp)
 {
-       xfs_daddr_t     offset;
-       xfs_caddr_t     ptr;
+       xfs_daddr_t     offset = blk_no & ((xfs_daddr_t)log->l_sectBBsize - 1);
 
-       offset = blk_no & ((xfs_daddr_t) log->l_sectBBsize - 1);
-       ptr = XFS_BUF_PTR(bp) + BBTOB(offset);
-
-       ASSERT(ptr + BBTOB(nbblks) <= XFS_BUF_PTR(bp) + XFS_BUF_SIZE(bp));
-
-       return ptr;
+       ASSERT(BBTOB(offset + nbblks) <= XFS_BUF_SIZE(bp));
+       return XFS_BUF_PTR(bp) + BBTOB(offset);
 }
 
 
@@ -3203,7 +3198,7 @@ xlog_recover_process_one_iunlink(
        int                             error;
 
        ino = XFS_AGINO_TO_INO(mp, agno, agino);
-       error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
+       error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
        if (error)
                goto fail;
 
index d7bf38c8cd1c47dc5bc19887072889267825bd91..69f62d8b2816c52389f4947c9d86b3958ccf57a6 100644 (file)
@@ -268,10 +268,10 @@ xfs_sb_validate_fsb_count(
 
 #if XFS_BIG_BLKNOS     /* Limited by ULONG_MAX of page cache index */
        if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX)
-               return E2BIG;
+               return EFBIG;
 #else                  /* Limited by UINT_MAX of sectors */
        if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX)
-               return E2BIG;
+               return EFBIG;
 #endif
        return 0;
 }
@@ -393,7 +393,7 @@ xfs_mount_validate_sb(
            xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
                xfs_fs_mount_cmn_err(flags,
                        "file system too large to be mounted on this system.");
-               return XFS_ERROR(E2BIG);
+               return XFS_ERROR(EFBIG);
        }
 
        if (unlikely(sbp->sb_inprogress)) {
@@ -413,17 +413,6 @@ xfs_mount_validate_sb(
        return 0;
 }
 
-STATIC void
-xfs_initialize_perag_icache(
-       xfs_perag_t     *pag)
-{
-       if (!pag->pag_ici_init) {
-               rwlock_init(&pag->pag_ici_lock);
-               INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
-               pag->pag_ici_init = 1;
-       }
-}
-
 int
 xfs_initialize_perag(
        xfs_mount_t     *mp,
@@ -436,13 +425,8 @@ xfs_initialize_perag(
        xfs_agino_t     agino;
        xfs_ino_t       ino;
        xfs_sb_t        *sbp = &mp->m_sb;
-       xfs_ino_t       max_inum = XFS_MAXINUMBER_32;
        int             error = -ENOMEM;
 
-       /* Check to see if the filesystem can overflow 32 bit inodes */
-       agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
-       ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
-
        /*
         * Walk the current per-ag tree so we don't try to initialise AGs
         * that already exist (growfs case). Allocate and insert all the
@@ -456,11 +440,18 @@ xfs_initialize_perag(
                }
                if (!first_initialised)
                        first_initialised = index;
+
                pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL);
                if (!pag)
                        goto out_unwind;
+               pag->pag_agno = index;
+               pag->pag_mount = mp;
+               rwlock_init(&pag->pag_ici_lock);
+               INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
+
                if (radix_tree_preload(GFP_NOFS))
                        goto out_unwind;
+
                spin_lock(&mp->m_perag_lock);
                if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
                        BUG();
@@ -469,25 +460,26 @@ xfs_initialize_perag(
                        error = -EEXIST;
                        goto out_unwind;
                }
-               pag->pag_agno = index;
-               pag->pag_mount = mp;
                spin_unlock(&mp->m_perag_lock);
                radix_tree_preload_end();
        }
 
-       /* Clear the mount flag if no inode can overflow 32 bits
-        * on this filesystem, or if specifically requested..
+       /*
+        * If we mount with the inode64 option, or no inode overflows
+        * the legacy 32-bit address space clear the inode32 option.
         */
-       if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > max_inum) {
+       agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
+       ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
+
+       if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
                mp->m_flags |= XFS_MOUNT_32BITINODES;
-       } else {
+       else
                mp->m_flags &= ~XFS_MOUNT_32BITINODES;
-       }
 
-       /* If we can overflow then setup the ag headers accordingly */
        if (mp->m_flags & XFS_MOUNT_32BITINODES) {
-               /* Calculate how much should be reserved for inodes to
-                * meet the max inode percentage.
+               /*
+                * Calculate how much should be reserved for inodes to meet
+                * the max inode percentage.
                 */
                if (mp->m_maxicount) {
                        __uint64_t      icount;
@@ -500,30 +492,28 @@ xfs_initialize_perag(
                } else {
                        max_metadata = agcount;
                }
+
                for (index = 0; index < agcount; index++) {
                        ino = XFS_AGINO_TO_INO(mp, index, agino);
-                       if (ino > max_inum) {
+                       if (ino > XFS_MAXINUMBER_32) {
                                index++;
                                break;
                        }
 
-                       /* This ag is preferred for inodes */
                        pag = xfs_perag_get(mp, index);
                        pag->pagi_inodeok = 1;
                        if (index < max_metadata)
                                pag->pagf_metadata = 1;
-                       xfs_initialize_perag_icache(pag);
                        xfs_perag_put(pag);
                }
        } else {
-               /* Setup default behavior for smaller filesystems */
                for (index = 0; index < agcount; index++) {
                        pag = xfs_perag_get(mp, index);
                        pag->pagi_inodeok = 1;
-                       xfs_initialize_perag_icache(pag);
                        xfs_perag_put(pag);
                }
        }
+
        if (maxagi)
                *maxagi = index;
        return 0;
@@ -1009,7 +999,7 @@ xfs_check_sizes(xfs_mount_t *mp)
        d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
        if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
                cmn_err(CE_WARN, "XFS: size check 1 failed");
-               return XFS_ERROR(E2BIG);
+               return XFS_ERROR(EFBIG);
        }
        error = xfs_read_buf(mp, mp->m_ddev_targp,
                             d - XFS_FSS_TO_BB(mp, 1),
@@ -1019,7 +1009,7 @@ xfs_check_sizes(xfs_mount_t *mp)
        } else {
                cmn_err(CE_WARN, "XFS: size check 2 failed");
                if (error == ENOSPC)
-                       error = XFS_ERROR(E2BIG);
+                       error = XFS_ERROR(EFBIG);
                return error;
        }
 
@@ -1027,7 +1017,7 @@ xfs_check_sizes(xfs_mount_t *mp)
                d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
                if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
                        cmn_err(CE_WARN, "XFS: size check 3 failed");
-                       return XFS_ERROR(E2BIG);
+                       return XFS_ERROR(EFBIG);
                }
                error = xfs_read_buf(mp, mp->m_logdev_targp,
                                     d - XFS_FSB_TO_BB(mp, 1),
@@ -1037,7 +1027,7 @@ xfs_check_sizes(xfs_mount_t *mp)
                } else {
                        cmn_err(CE_WARN, "XFS: size check 3 failed");
                        if (error == ENOSPC)
-                               error = XFS_ERROR(E2BIG);
+                               error = XFS_ERROR(EFBIG);
                        return error;
                }
        }
@@ -1254,7 +1244,7 @@ xfs_mountfs(
         * Allocate and initialize the per-ag data.
         */
        spin_lock_init(&mp->m_perag_lock);
-       INIT_RADIX_TREE(&mp->m_perag_tree, GFP_NOFS);
+       INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
        error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
        if (error) {
                cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error);
@@ -1310,7 +1300,7 @@ xfs_mountfs(
         * Get and sanity-check the root inode.
         * Save the pointer to it in the mount structure.
         */
-       error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip, 0);
+       error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip);
        if (error) {
                cmn_err(CE_WARN, "XFS: failed to read root inode");
                goto out_log_dealloc;
index 6be05f756d59d544c82576d307266ce5b739f893..a2d32ce335aa681c3beab111f4c844873353f6af 100644 (file)
@@ -2247,7 +2247,7 @@ xfs_rtmount_init(
                cmn_err(CE_WARN, "XFS: realtime mount -- %llu != %llu",
                        (unsigned long long) XFS_BB_TO_FSB(mp, d),
                        (unsigned long long) mp->m_sb.sb_rblocks);
-               return XFS_ERROR(E2BIG);
+               return XFS_ERROR(EFBIG);
        }
        error = xfs_read_buf(mp, mp->m_rtdev_targp,
                                d - XFS_FSB_TO_BB(mp, 1),
@@ -2256,7 +2256,7 @@ xfs_rtmount_init(
                cmn_err(CE_WARN,
        "XFS: realtime mount -- xfs_read_buf failed, returned %d", error);
                if (error == ENOSPC)
-                       return XFS_ERROR(E2BIG);
+                       return XFS_ERROR(EFBIG);
                return error;
        }
        xfs_buf_relse(bp);
@@ -2277,12 +2277,12 @@ xfs_rtmount_inodes(
        sbp = &mp->m_sb;
        if (sbp->sb_rbmino == NULLFSINO)
                return 0;
-       error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip, 0);
+       error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip);
        if (error)
                return error;
        ASSERT(mp->m_rbmip != NULL);
        ASSERT(sbp->sb_rsumino != NULLFSINO);
-       error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip, 0);
+       error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip);
        if (error) {
                IRELE(mp->m_rbmip);
                return error;
index b2d67adb6a08f4f9f801168337e0c81c4bb00d5d..ff614c29b44142da429bb33db904afdf843469ad 100644 (file)
@@ -147,7 +147,16 @@ xfs_growfs_rt(
 # define xfs_rtfree_extent(t,b,l)                       (ENOSYS)
 # define xfs_rtpick_extent(m,t,l,rb)                    (ENOSYS)
 # define xfs_growfs_rt(mp,in)                           (ENOSYS)
-# define xfs_rtmount_init(m)    (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
+static inline int              /* error */
+xfs_rtmount_init(
+       xfs_mount_t     *mp)    /* file system mount structure */
+{
+       if (mp->m_sb.sb_rblocks == 0)
+               return 0;
+
+       cmn_err(CE_WARN, "XFS: Not built with CONFIG_XFS_RT");
+       return ENOSYS;
+}
 # define xfs_rtmount_inodes(m)  (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
 # define xfs_rtunmount_inodes(m)
 #endif /* CONFIG_XFS_RT */
index ce558efa2ea02a8ba9fd1f8b2bb2bad121a64071..28547dfce037643fb19744ed36906d5e7f3c1c76 100644 (file)
 
 kmem_zone_t    *xfs_trans_zone;
 
+
 /*
- * Reservation functions here avoid a huge stack in xfs_trans_init
- * due to register overflow from temporaries in the calculations.
+ * Various log reservation values.
+ *
+ * These are based on the size of the file system block because that is what
+ * most transactions manipulate.  Each adds in an additional 128 bytes per
+ * item logged to try to account for the overhead of the transaction mechanism.
+ *
+ * Note:  Most of the reservations underestimate the number of allocation
+ * groups into which they could free extents in the xfs_bmap_finish() call.
+ * This is because the number in the worst case is quite high and quite
+ * unusual.  In order to fix this we need to change xfs_bmap_finish() to free
+ * extents in only a single AG at a time.  This will require changes to the
+ * EFI code as well, however, so that the EFI for the extents not freed is
+ * logged again in each transaction.  See SGI PV #261917.
+ *
+ * Reservation functions here avoid a huge stack in xfs_trans_init due to
+ * register overflow from temporaries in the calculations.
+ */
+
+
+/*
+ * In a write transaction we can allocate a maximum of 2
+ * extents.  This gives:
+ *    the inode getting the new extents: inode size
+ *    the inode's bmap btree: max depth * block size
+ *    the agfs of the ags from which the extents are allocated: 2 * sector
+ *    the superblock free block counter: sector size
+ *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
+ * And the bmap_finish transaction can free bmap blocks in a join:
+ *    the agfs of the ags containing the blocks: 2 * sector size
+ *    the agfls of the ags containing the blocks: 2 * sector size
+ *    the super block free block counter: sector size
+ *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
  */
 STATIC uint
-xfs_calc_write_reservation(xfs_mount_t *mp)
+xfs_calc_write_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_WRITE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               MAX((mp->m_sb.sb_inodesize +
+                    XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) +
+                    2 * mp->m_sb.sb_sectsize +
+                    mp->m_sb.sb_sectsize +
+                    XFS_ALLOCFREE_LOG_RES(mp, 2) +
+                    128 * (4 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) +
+                           XFS_ALLOCFREE_LOG_COUNT(mp, 2))),
+                   (2 * mp->m_sb.sb_sectsize +
+                    2 * mp->m_sb.sb_sectsize +
+                    mp->m_sb.sb_sectsize +
+                    XFS_ALLOCFREE_LOG_RES(mp, 2) +
+                    128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
 }
 
+/*
+ * In truncating a file we free up to two extents at once.  We can modify:
+ *    the inode being truncated: inode size
+ *    the inode's bmap btree: (max depth + 1) * block size
+ * And the bmap_finish transaction can free the blocks and bmap blocks:
+ *    the agf for each of the ags: 4 * sector size
+ *    the agfl for each of the ags: 4 * sector size
+ *    the super block to reflect the freed blocks: sector size
+ *    worst case split in allocation btrees per extent assuming 4 extents:
+ *             4 exts * 2 trees * (2 * max depth - 1) * block size
+ *    the inode btree: max depth * blocksize
+ *    the allocation btrees: 2 trees * (max depth - 1) * block size
+ */
 STATIC uint
-xfs_calc_itruncate_reservation(xfs_mount_t *mp)
+xfs_calc_itruncate_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_ITRUNCATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               MAX((mp->m_sb.sb_inodesize +
+                    XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1) +
+                    128 * (2 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))),
+                   (4 * mp->m_sb.sb_sectsize +
+                    4 * mp->m_sb.sb_sectsize +
+                    mp->m_sb.sb_sectsize +
+                    XFS_ALLOCFREE_LOG_RES(mp, 4) +
+                    128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4)) +
+                    128 * 5 +
+                    XFS_ALLOCFREE_LOG_RES(mp, 1) +
+                    128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
+                           XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
 }
 
+/*
+ * In renaming a files we can modify:
+ *    the four inodes involved: 4 * inode size
+ *    the two directory btrees: 2 * (max depth + v2) * dir block size
+ *    the two directory bmap btrees: 2 * max depth * block size
+ * And the bmap_finish transaction can free dir and bmap blocks (two sets
+ *     of bmap blocks) giving:
+ *    the agf for the ags in which the blocks live: 3 * sector size
+ *    the agfl for the ags in which the blocks live: 3 * sector size
+ *    the superblock for the free block count: sector size
+ *    the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
+ */
 STATIC uint
-xfs_calc_rename_reservation(xfs_mount_t *mp)
+xfs_calc_rename_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_RENAME_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               MAX((4 * mp->m_sb.sb_inodesize +
+                    2 * XFS_DIROP_LOG_RES(mp) +
+                    128 * (4 + 2 * XFS_DIROP_LOG_COUNT(mp))),
+                   (3 * mp->m_sb.sb_sectsize +
+                    3 * mp->m_sb.sb_sectsize +
+                    mp->m_sb.sb_sectsize +
+                    XFS_ALLOCFREE_LOG_RES(mp, 3) +
+                    128 * (7 + XFS_ALLOCFREE_LOG_COUNT(mp, 3))));
 }
 
+/*
+ * For creating a link to an inode:
+ *    the parent directory inode: inode size
+ *    the linked inode: inode size
+ *    the directory btree could split: (max depth + v2) * dir block size
+ *    the directory bmap btree could join or split: (max depth + v2) * blocksize
+ * And the bmap_finish transaction can free some bmap blocks giving:
+ *    the agf for the ag in which the blocks live: sector size
+ *    the agfl for the ag in which the blocks live: sector size
+ *    the superblock for the free block count: sector size
+ *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
+ */
 STATIC uint
-xfs_calc_link_reservation(xfs_mount_t *mp)
+xfs_calc_link_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_LINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               MAX((mp->m_sb.sb_inodesize +
+                    mp->m_sb.sb_inodesize +
+                    XFS_DIROP_LOG_RES(mp) +
+                    128 * (2 + XFS_DIROP_LOG_COUNT(mp))),
+                   (mp->m_sb.sb_sectsize +
+                    mp->m_sb.sb_sectsize +
+                    mp->m_sb.sb_sectsize +
+                    XFS_ALLOCFREE_LOG_RES(mp, 1) +
+                    128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
 }
 
+/*
+ * For removing a directory entry we can modify:
+ *    the parent directory inode: inode size
+ *    the removed inode: inode size
+ *    the directory btree could join: (max depth + v2) * dir block size
+ *    the directory bmap btree could join or split: (max depth + v2) * blocksize
+ * And the bmap_finish transaction can free the dir and bmap blocks giving:
+ *    the agf for the ag in which the blocks live: 2 * sector size
+ *    the agfl for the ag in which the blocks live: 2 * sector size
+ *    the superblock for the free block count: sector size
+ *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
+ */
 STATIC uint
-xfs_calc_remove_reservation(xfs_mount_t *mp)
+xfs_calc_remove_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_REMOVE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               MAX((mp->m_sb.sb_inodesize +
+                    mp->m_sb.sb_inodesize +
+                    XFS_DIROP_LOG_RES(mp) +
+                    128 * (2 + XFS_DIROP_LOG_COUNT(mp))),
+                   (2 * mp->m_sb.sb_sectsize +
+                    2 * mp->m_sb.sb_sectsize +
+                    mp->m_sb.sb_sectsize +
+                    XFS_ALLOCFREE_LOG_RES(mp, 2) +
+                    128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
 }
 
+/*
+ * For symlink we can modify:
+ *    the parent directory inode: inode size
+ *    the new inode: inode size
+ *    the inode btree entry: 1 block
+ *    the directory btree: (max depth + v2) * dir block size
+ *    the directory inode's bmap btree: (max depth + v2) * block size
+ *    the blocks for the symlink: 1 kB
+ * Or in the first xact we allocate some inodes giving:
+ *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
+ *    the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
+ *    the inode btree: max depth * blocksize
+ *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
+ */
 STATIC uint
-xfs_calc_symlink_reservation(xfs_mount_t *mp)
+xfs_calc_symlink_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_SYMLINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               MAX((mp->m_sb.sb_inodesize +
+                    mp->m_sb.sb_inodesize +
+                    XFS_FSB_TO_B(mp, 1) +
+                    XFS_DIROP_LOG_RES(mp) +
+                    1024 +
+                    128 * (4 + XFS_DIROP_LOG_COUNT(mp))),
+                   (2 * mp->m_sb.sb_sectsize +
+                    XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) +
+                    XFS_FSB_TO_B(mp, mp->m_in_maxlevels) +
+                    XFS_ALLOCFREE_LOG_RES(mp, 1) +
+                    128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
+                           XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
 }
 
+/*
+ * For create we can modify:
+ *    the parent directory inode: inode size
+ *    the new inode: inode size
+ *    the inode btree entry: block size
+ *    the superblock for the nlink flag: sector size
+ *    the directory btree: (max depth + v2) * dir block size
+ *    the directory inode's bmap btree: (max depth + v2) * block size
+ * Or in the first xact we allocate some inodes giving:
+ *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
+ *    the superblock for the nlink flag: sector size
+ *    the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
+ *    the inode btree: max depth * blocksize
+ *    the allocation btrees: 2 trees * (max depth - 1) * block size
+ */
 STATIC uint
-xfs_calc_create_reservation(xfs_mount_t *mp)
+xfs_calc_create_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_CREATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               MAX((mp->m_sb.sb_inodesize +
+                    mp->m_sb.sb_inodesize +
+                    mp->m_sb.sb_sectsize +
+                    XFS_FSB_TO_B(mp, 1) +
+                    XFS_DIROP_LOG_RES(mp) +
+                    128 * (3 + XFS_DIROP_LOG_COUNT(mp))),
+                   (3 * mp->m_sb.sb_sectsize +
+                    XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) +
+                    XFS_FSB_TO_B(mp, mp->m_in_maxlevels) +
+                    XFS_ALLOCFREE_LOG_RES(mp, 1) +
+                    128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
+                           XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
 }
 
+/*
+ * Making a new directory is the same as creating a new file.
+ */
 STATIC uint
-xfs_calc_mkdir_reservation(xfs_mount_t *mp)
+xfs_calc_mkdir_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_MKDIR_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return xfs_calc_create_reservation(mp);
 }
 
+/*
+ * In freeing an inode we can modify:
+ *    the inode being freed: inode size
+ *    the super block free inode counter: sector size
+ *    the agi hash list and counters: sector size
+ *    the inode btree entry: block size
+ *    the on disk inode before ours in the agi hash list: inode cluster size
+ *    the inode btree: max depth * blocksize
+ *    the allocation btrees: 2 trees * (max depth - 1) * block size
+ */
 STATIC uint
-xfs_calc_ifree_reservation(xfs_mount_t *mp)
+xfs_calc_ifree_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_IFREE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               mp->m_sb.sb_inodesize +
+               mp->m_sb.sb_sectsize +
+               mp->m_sb.sb_sectsize +
+               XFS_FSB_TO_B(mp, 1) +
+               MAX((__uint16_t)XFS_FSB_TO_B(mp, 1),
+                   XFS_INODE_CLUSTER_SIZE(mp)) +
+               128 * 5 +
+               XFS_ALLOCFREE_LOG_RES(mp, 1) +
+               128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
+                      XFS_ALLOCFREE_LOG_COUNT(mp, 1));
 }
 
+/*
+ * When only changing the inode we log the inode and possibly the superblock
+ * We also add a bit of slop for the transaction stuff.
+ */
 STATIC uint
-xfs_calc_ichange_reservation(xfs_mount_t *mp)
+xfs_calc_ichange_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_ICHANGE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               mp->m_sb.sb_inodesize +
+               mp->m_sb.sb_sectsize +
+               512;
+
 }
 
+/*
+ * Growing the data section of the filesystem.
+ *     superblock
+ *     agi and agf
+ *     allocation btrees
+ */
 STATIC uint
-xfs_calc_growdata_reservation(xfs_mount_t *mp)
+xfs_calc_growdata_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_GROWDATA_LOG_RES(mp);
+       return mp->m_sb.sb_sectsize * 3 +
+               XFS_ALLOCFREE_LOG_RES(mp, 1) +
+               128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1));
 }
 
+/*
+ * Growing the rt section of the filesystem.
+ * In the first set of transactions (ALLOC) we allocate space to the
+ * bitmap or summary files.
+ *     superblock: sector size
+ *     agf of the ag from which the extent is allocated: sector size
+ *     bmap btree for bitmap/summary inode: max depth * blocksize
+ *     bitmap/summary inode: inode size
+ *     allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
+ */
 STATIC uint
-xfs_calc_growrtalloc_reservation(xfs_mount_t *mp)
+xfs_calc_growrtalloc_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_GROWRTALLOC_LOG_RES(mp);
+       return 2 * mp->m_sb.sb_sectsize +
+               XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) +
+               mp->m_sb.sb_inodesize +
+               XFS_ALLOCFREE_LOG_RES(mp, 1) +
+               128 * (3 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) +
+                      XFS_ALLOCFREE_LOG_COUNT(mp, 1));
 }
 
+/*
+ * Growing the rt section of the filesystem.
+ * In the second set of transactions (ZERO) we zero the new metadata blocks.
+ *     one bitmap/summary block: blocksize
+ */
 STATIC uint
-xfs_calc_growrtzero_reservation(xfs_mount_t *mp)
+xfs_calc_growrtzero_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_GROWRTZERO_LOG_RES(mp);
+       return mp->m_sb.sb_blocksize + 128;
 }
 
+/*
+ * Growing the rt section of the filesystem.
+ * In the third set of transactions (FREE) we update metadata without
+ * allocating any new blocks.
+ *     superblock: sector size
+ *     bitmap inode: inode size
+ *     summary inode: inode size
+ *     one bitmap block: blocksize
+ *     summary blocks: new summary size
+ */
 STATIC uint
-xfs_calc_growrtfree_reservation(xfs_mount_t *mp)
+xfs_calc_growrtfree_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_GROWRTFREE_LOG_RES(mp);
+       return mp->m_sb.sb_sectsize +
+               2 * mp->m_sb.sb_inodesize +
+               mp->m_sb.sb_blocksize +
+               mp->m_rsumsize +
+               128 * 5;
 }
 
+/*
+ * Logging the inode modification timestamp on a synchronous write.
+ *     inode
+ */
 STATIC uint
-xfs_calc_swrite_reservation(xfs_mount_t *mp)
+xfs_calc_swrite_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_SWRITE_LOG_RES(mp);
+       return mp->m_sb.sb_inodesize + 128;
 }
 
+/*
+ * Logging the inode mode bits when writing a setuid/setgid file
+ *     inode
+ */
 STATIC uint
 xfs_calc_writeid_reservation(xfs_mount_t *mp)
 {
-       return XFS_CALC_WRITEID_LOG_RES(mp);
+       return mp->m_sb.sb_inodesize + 128;
 }
 
+/*
+ * Converting the inode from non-attributed to attributed.
+ *     the inode being converted: inode size
+ *     agf block and superblock (for block allocation)
+ *     the new block (directory sized)
+ *     bmap blocks for the new directory block
+ *     allocation btrees
+ */
 STATIC uint
-xfs_calc_addafork_reservation(xfs_mount_t *mp)
+xfs_calc_addafork_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_ADDAFORK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               mp->m_sb.sb_inodesize +
+               mp->m_sb.sb_sectsize * 2 +
+               mp->m_dirblksize +
+               XFS_FSB_TO_B(mp, XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) +
+               XFS_ALLOCFREE_LOG_RES(mp, 1) +
+               128 * (4 + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1 +
+                      XFS_ALLOCFREE_LOG_COUNT(mp, 1));
 }
 
+/*
+ * Removing the attribute fork of a file
+ *    the inode being truncated: inode size
+ *    the inode's bmap btree: max depth * block size
+ * And the bmap_finish transaction can free the blocks and bmap blocks:
+ *    the agf for each of the ags: 4 * sector size
+ *    the agfl for each of the ags: 4 * sector size
+ *    the super block to reflect the freed blocks: sector size
+ *    worst case split in allocation btrees per extent assuming 4 extents:
+ *             4 exts * 2 trees * (2 * max depth - 1) * block size
+ */
 STATIC uint
-xfs_calc_attrinval_reservation(xfs_mount_t *mp)
+xfs_calc_attrinval_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_ATTRINVAL_LOG_RES(mp);
+       return MAX((mp->m_sb.sb_inodesize +
+                   XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
+                   128 * (1 + XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK))),
+                  (4 * mp->m_sb.sb_sectsize +
+                   4 * mp->m_sb.sb_sectsize +
+                   mp->m_sb.sb_sectsize +
+                   XFS_ALLOCFREE_LOG_RES(mp, 4) +
+                   128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))));
 }
 
+/*
+ * Setting an attribute.
+ *     the inode getting the attribute
+ *     the superblock for allocations
+ *     the agfs extents are allocated from
+ *     the attribute btree * max depth
+ *     the inode allocation btree
+ * Since attribute transaction space is dependent on the size of the attribute,
+ * the calculation is done partially at mount time and partially at runtime.
+ */
 STATIC uint
-xfs_calc_attrset_reservation(xfs_mount_t *mp)
+xfs_calc_attrset_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_ATTRSET_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               mp->m_sb.sb_inodesize +
+               mp->m_sb.sb_sectsize +
+               XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) +
+               128 * (2 + XFS_DA_NODE_MAXDEPTH);
 }
 
+/*
+ * Removing an attribute.
+ *    the inode: inode size
+ *    the attribute btree could join: max depth * block size
+ *    the inode bmap btree could join or split: max depth * block size
+ * And the bmap_finish transaction can free the attr blocks freed giving:
+ *    the agf for the ag in which the blocks live: 2 * sector size
+ *    the agfl for the ag in which the blocks live: 2 * sector size
+ *    the superblock for the free block count: sector size
+ *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
+ */
 STATIC uint
-xfs_calc_attrrm_reservation(xfs_mount_t *mp)
+xfs_calc_attrrm_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_ATTRRM_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+       return XFS_DQUOT_LOGRES(mp) +
+               MAX((mp->m_sb.sb_inodesize +
+                    XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) +
+                    XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
+                    128 * (1 + XFS_DA_NODE_MAXDEPTH +
+                           XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))),
+                   (2 * mp->m_sb.sb_sectsize +
+                    2 * mp->m_sb.sb_sectsize +
+                    mp->m_sb.sb_sectsize +
+                    XFS_ALLOCFREE_LOG_RES(mp, 2) +
+                    128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
 }
 
+/*
+ * Clearing a bad agino number in an agi hash bucket.
+ */
 STATIC uint
-xfs_calc_clear_agi_bucket_reservation(xfs_mount_t *mp)
+xfs_calc_clear_agi_bucket_reservation(
+       struct xfs_mount        *mp)
 {
-       return XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp);
+       return mp->m_sb.sb_sectsize + 128;
 }
 
 /*
@@ -184,11 +539,10 @@ xfs_calc_clear_agi_bucket_reservation(xfs_mount_t *mp)
  */
 void
 xfs_trans_init(
-       xfs_mount_t     *mp)
+       struct xfs_mount        *mp)
 {
-       xfs_trans_reservations_t        *resp;
+       struct xfs_trans_reservations *resp = &mp->m_reservations;
 
-       resp = &(mp->m_reservations);
        resp->tr_write = xfs_calc_write_reservation(mp);
        resp->tr_itruncate = xfs_calc_itruncate_reservation(mp);
        resp->tr_rename = xfs_calc_rename_reservation(mp);
index 8c69e7824f68439d01d0b27009f961dbd8e0c947..e639e8e9a2a978ed6404725ce52b6f4cdbe840ba 100644 (file)
@@ -299,24 +299,6 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
 #define        XFS_TRANS_SB_REXTSLOG           0x00002000
 
 
-/*
- * Various log reservation values.
- * These are based on the size of the file system block
- * because that is what most transactions manipulate.
- * Each adds in an additional 128 bytes per item logged to
- * try to account for the overhead of the transaction mechanism.
- *
- * Note:
- * Most of the reservations underestimate the number of allocation
- * groups into which they could free extents in the xfs_bmap_finish()
- * call.  This is because the number in the worst case is quite high
- * and quite unusual.  In order to fix this we need to change
- * xfs_bmap_finish() to free extents in only a single AG at a time.
- * This will require changes to the EFI code as well, however, so that
- * the EFI for the extents not freed is logged again in each transaction.
- * See bug 261917.
- */
-
 /*
  * Per-extent log reservation for the allocation btree changes
  * involved in freeing or allocating an extent.
@@ -341,429 +323,36 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
        (XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK) + \
         XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1)
 
-/*
- * In a write transaction we can allocate a maximum of 2
- * extents.  This gives:
- *    the inode getting the new extents: inode size
- *    the inode's bmap btree: max depth * block size
- *    the agfs of the ags from which the extents are allocated: 2 * sector
- *    the superblock free block counter: sector size
- *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
- * And the bmap_finish transaction can free bmap blocks in a join:
- *    the agfs of the ags containing the blocks: 2 * sector size
- *    the agfls of the ags containing the blocks: 2 * sector size
- *    the super block free block counter: sector size
- *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
- */
-#define XFS_CALC_WRITE_LOG_RES(mp) \
-       (MAX( \
-        ((mp)->m_sb.sb_inodesize + \
-         XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + \
-         (2 * (mp)->m_sb.sb_sectsize) + \
-         (mp)->m_sb.sb_sectsize + \
-         XFS_ALLOCFREE_LOG_RES(mp, 2) + \
-         (128 * (4 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + XFS_ALLOCFREE_LOG_COUNT(mp, 2)))),\
-        ((2 * (mp)->m_sb.sb_sectsize) + \
-         (2 * (mp)->m_sb.sb_sectsize) + \
-         (mp)->m_sb.sb_sectsize + \
-         XFS_ALLOCFREE_LOG_RES(mp, 2) + \
-         (128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
 
 #define        XFS_WRITE_LOG_RES(mp)   ((mp)->m_reservations.tr_write)
-
-/*
- * In truncating a file we free up to two extents at once.  We can modify:
- *    the inode being truncated: inode size
- *    the inode's bmap btree: (max depth + 1) * block size
- * And the bmap_finish transaction can free the blocks and bmap blocks:
- *    the agf for each of the ags: 4 * sector size
- *    the agfl for each of the ags: 4 * sector size
- *    the super block to reflect the freed blocks: sector size
- *    worst case split in allocation btrees per extent assuming 4 extents:
- *             4 exts * 2 trees * (2 * max depth - 1) * block size
- *    the inode btree: max depth * blocksize
- *    the allocation btrees: 2 trees * (max depth - 1) * block size
- */
-#define        XFS_CALC_ITRUNCATE_LOG_RES(mp) \
-       (MAX( \
-        ((mp)->m_sb.sb_inodesize + \
-         XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1) + \
-         (128 * (2 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)))), \
-        ((4 * (mp)->m_sb.sb_sectsize) + \
-         (4 * (mp)->m_sb.sb_sectsize) + \
-         (mp)->m_sb.sb_sectsize + \
-         XFS_ALLOCFREE_LOG_RES(mp, 4) + \
-         (128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))) + \
-         (128 * 5) + \
-         XFS_ALLOCFREE_LOG_RES(mp, 1) + \
-          (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
-           XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
-
 #define        XFS_ITRUNCATE_LOG_RES(mp)   ((mp)->m_reservations.tr_itruncate)
-
-/*
- * In renaming a files we can modify:
- *    the four inodes involved: 4 * inode size
- *    the two directory btrees: 2 * (max depth + v2) * dir block size
- *    the two directory bmap btrees: 2 * max depth * block size
- * And the bmap_finish transaction can free dir and bmap blocks (two sets
- *     of bmap blocks) giving:
- *    the agf for the ags in which the blocks live: 3 * sector size
- *    the agfl for the ags in which the blocks live: 3 * sector size
- *    the superblock for the free block count: sector size
- *    the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
- */
-#define        XFS_CALC_RENAME_LOG_RES(mp) \
-       (MAX( \
-        ((4 * (mp)->m_sb.sb_inodesize) + \
-         (2 * XFS_DIROP_LOG_RES(mp)) + \
-         (128 * (4 + 2 * XFS_DIROP_LOG_COUNT(mp)))), \
-        ((3 * (mp)->m_sb.sb_sectsize) + \
-         (3 * (mp)->m_sb.sb_sectsize) + \
-         (mp)->m_sb.sb_sectsize + \
-         XFS_ALLOCFREE_LOG_RES(mp, 3) + \
-         (128 * (7 + XFS_ALLOCFREE_LOG_COUNT(mp, 3))))))
-
 #define        XFS_RENAME_LOG_RES(mp)  ((mp)->m_reservations.tr_rename)
-
-/*
- * For creating a link to an inode:
- *    the parent directory inode: inode size
- *    the linked inode: inode size
- *    the directory btree could split: (max depth + v2) * dir block size
- *    the directory bmap btree could join or split: (max depth + v2) * blocksize
- * And the bmap_finish transaction can free some bmap blocks giving:
- *    the agf for the ag in which the blocks live: sector size
- *    the agfl for the ag in which the blocks live: sector size
- *    the superblock for the free block count: sector size
- *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
- */
-#define        XFS_CALC_LINK_LOG_RES(mp) \
-       (MAX( \
-        ((mp)->m_sb.sb_inodesize + \
-         (mp)->m_sb.sb_inodesize + \
-         XFS_DIROP_LOG_RES(mp) + \
-         (128 * (2 + XFS_DIROP_LOG_COUNT(mp)))), \
-        ((mp)->m_sb.sb_sectsize + \
-         (mp)->m_sb.sb_sectsize + \
-         (mp)->m_sb.sb_sectsize + \
-         XFS_ALLOCFREE_LOG_RES(mp, 1) + \
-         (128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
-
 #define        XFS_LINK_LOG_RES(mp)    ((mp)->m_reservations.tr_link)
-
-/*
- * For removing a directory entry we can modify:
- *    the parent directory inode: inode size
- *    the removed inode: inode size
- *    the directory btree could join: (max depth + v2) * dir block size
- *    the directory bmap btree could join or split: (max depth + v2) * blocksize
- * And the bmap_finish transaction can free the dir and bmap blocks giving:
- *    the agf for the ag in which the blocks live: 2 * sector size
- *    the agfl for the ag in which the blocks live: 2 * sector size
- *    the superblock for the free block count: sector size
- *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
- */
-#define        XFS_CALC_REMOVE_LOG_RES(mp)     \
-       (MAX( \
-        ((mp)->m_sb.sb_inodesize + \
-         (mp)->m_sb.sb_inodesize + \
-         XFS_DIROP_LOG_RES(mp) + \
-         (128 * (2 + XFS_DIROP_LOG_COUNT(mp)))), \
-        ((2 * (mp)->m_sb.sb_sectsize) + \
-         (2 * (mp)->m_sb.sb_sectsize) + \
-         (mp)->m_sb.sb_sectsize + \
-         XFS_ALLOCFREE_LOG_RES(mp, 2) + \
-         (128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
-
 #define        XFS_REMOVE_LOG_RES(mp)  ((mp)->m_reservations.tr_remove)
-
-/*
- * For symlink we can modify:
- *    the parent directory inode: inode size
- *    the new inode: inode size
- *    the inode btree entry: 1 block
- *    the directory btree: (max depth + v2) * dir block size
- *    the directory inode's bmap btree: (max depth + v2) * block size
- *    the blocks for the symlink: 1 kB
- * Or in the first xact we allocate some inodes giving:
- *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
- *    the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
- *    the inode btree: max depth * blocksize
- *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
- */
-#define        XFS_CALC_SYMLINK_LOG_RES(mp)            \
-       (MAX( \
-        ((mp)->m_sb.sb_inodesize + \
-         (mp)->m_sb.sb_inodesize + \
-         XFS_FSB_TO_B(mp, 1) + \
-         XFS_DIROP_LOG_RES(mp) + \
-         1024 + \
-         (128 * (4 + XFS_DIROP_LOG_COUNT(mp)))), \
-        (2 * (mp)->m_sb.sb_sectsize + \
-         XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \
-         XFS_FSB_TO_B((mp), (mp)->m_in_maxlevels) + \
-         XFS_ALLOCFREE_LOG_RES(mp, 1) + \
-         (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
-          XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
-
 #define        XFS_SYMLINK_LOG_RES(mp) ((mp)->m_reservations.tr_symlink)
-
-/*
- * For create we can modify:
- *    the parent directory inode: inode size
- *    the new inode: inode size
- *    the inode btree entry: block size
- *    the superblock for the nlink flag: sector size
- *    the directory btree: (max depth + v2) * dir block size
- *    the directory inode's bmap btree: (max depth + v2) * block size
- * Or in the first xact we allocate some inodes giving:
- *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
- *    the superblock for the nlink flag: sector size
- *    the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
- *    the inode btree: max depth * blocksize
- *    the allocation btrees: 2 trees * (max depth - 1) * block size
- */
-#define        XFS_CALC_CREATE_LOG_RES(mp)             \
-       (MAX( \
-        ((mp)->m_sb.sb_inodesize + \
-         (mp)->m_sb.sb_inodesize + \
-         (mp)->m_sb.sb_sectsize + \
-         XFS_FSB_TO_B(mp, 1) + \
-         XFS_DIROP_LOG_RES(mp) + \
-         (128 * (3 + XFS_DIROP_LOG_COUNT(mp)))), \
-        (3 * (mp)->m_sb.sb_sectsize + \
-         XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \
-         XFS_FSB_TO_B((mp), (mp)->m_in_maxlevels) + \
-         XFS_ALLOCFREE_LOG_RES(mp, 1) + \
-         (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
-          XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
-
 #define        XFS_CREATE_LOG_RES(mp)  ((mp)->m_reservations.tr_create)
-
-/*
- * Making a new directory is the same as creating a new file.
- */
-#define        XFS_CALC_MKDIR_LOG_RES(mp)      XFS_CALC_CREATE_LOG_RES(mp)
-
 #define        XFS_MKDIR_LOG_RES(mp)   ((mp)->m_reservations.tr_mkdir)
-
-/*
- * In freeing an inode we can modify:
- *    the inode being freed: inode size
- *    the super block free inode counter: sector size
- *    the agi hash list and counters: sector size
- *    the inode btree entry: block size
- *    the on disk inode before ours in the agi hash list: inode cluster size
- *    the inode btree: max depth * blocksize
- *    the allocation btrees: 2 trees * (max depth - 1) * block size
- */
-#define        XFS_CALC_IFREE_LOG_RES(mp) \
-       ((mp)->m_sb.sb_inodesize + \
-        (mp)->m_sb.sb_sectsize + \
-        (mp)->m_sb.sb_sectsize + \
-        XFS_FSB_TO_B((mp), 1) + \
-        MAX((__uint16_t)XFS_FSB_TO_B((mp), 1), XFS_INODE_CLUSTER_SIZE(mp)) + \
-        (128 * 5) + \
-         XFS_ALLOCFREE_LOG_RES(mp, 1) + \
-         (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
-          XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
-
-
 #define        XFS_IFREE_LOG_RES(mp)   ((mp)->m_reservations.tr_ifree)
-
-/*
- * When only changing the inode we log the inode and possibly the superblock
- * We also add a bit of slop for the transaction stuff.
- */
-#define        XFS_CALC_ICHANGE_LOG_RES(mp)    ((mp)->m_sb.sb_inodesize + \
-                                        (mp)->m_sb.sb_sectsize + 512)
-
 #define        XFS_ICHANGE_LOG_RES(mp) ((mp)->m_reservations.tr_ichange)
-
-/*
- * Growing the data section of the filesystem.
- *     superblock
- *     agi and agf
- *     allocation btrees
- */
-#define        XFS_CALC_GROWDATA_LOG_RES(mp) \
-       ((mp)->m_sb.sb_sectsize * 3 + \
-        XFS_ALLOCFREE_LOG_RES(mp, 1) + \
-        (128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
-
 #define        XFS_GROWDATA_LOG_RES(mp)    ((mp)->m_reservations.tr_growdata)
-
-/*
- * Growing the rt section of the filesystem.
- * In the first set of transactions (ALLOC) we allocate space to the
- * bitmap or summary files.
- *     superblock: sector size
- *     agf of the ag from which the extent is allocated: sector size
- *     bmap btree for bitmap/summary inode: max depth * blocksize
- *     bitmap/summary inode: inode size
- *     allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
- */
-#define        XFS_CALC_GROWRTALLOC_LOG_RES(mp) \
-       (2 * (mp)->m_sb.sb_sectsize + \
-        XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + \
-        (mp)->m_sb.sb_inodesize + \
-        XFS_ALLOCFREE_LOG_RES(mp, 1) + \
-        (128 * \
-         (3 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + \
-          XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
-
 #define        XFS_GROWRTALLOC_LOG_RES(mp)     ((mp)->m_reservations.tr_growrtalloc)
-
-/*
- * Growing the rt section of the filesystem.
- * In the second set of transactions (ZERO) we zero the new metadata blocks.
- *     one bitmap/summary block: blocksize
- */
-#define        XFS_CALC_GROWRTZERO_LOG_RES(mp) \
-       ((mp)->m_sb.sb_blocksize + 128)
-
 #define        XFS_GROWRTZERO_LOG_RES(mp)      ((mp)->m_reservations.tr_growrtzero)
-
-/*
- * Growing the rt section of the filesystem.
- * In the third set of transactions (FREE) we update metadata without
- * allocating any new blocks.
- *     superblock: sector size
- *     bitmap inode: inode size
- *     summary inode: inode size
- *     one bitmap block: blocksize
- *     summary blocks: new summary size
- */
-#define        XFS_CALC_GROWRTFREE_LOG_RES(mp) \
-       ((mp)->m_sb.sb_sectsize + \
-        2 * (mp)->m_sb.sb_inodesize + \
-        (mp)->m_sb.sb_blocksize + \
-        (mp)->m_rsumsize + \
-        (128 * 5))
-
 #define        XFS_GROWRTFREE_LOG_RES(mp)      ((mp)->m_reservations.tr_growrtfree)
-
-/*
- * Logging the inode modification timestamp on a synchronous write.
- *     inode
- */
-#define        XFS_CALC_SWRITE_LOG_RES(mp) \
-       ((mp)->m_sb.sb_inodesize + 128)
-
 #define        XFS_SWRITE_LOG_RES(mp)  ((mp)->m_reservations.tr_swrite)
-
 /*
  * Logging the inode timestamps on an fsync -- same as SWRITE
  * as long as SWRITE logs the entire inode core
  */
 #define XFS_FSYNC_TS_LOG_RES(mp)        ((mp)->m_reservations.tr_swrite)
-
-/*
- * Logging the inode mode bits when writing a setuid/setgid file
- *     inode
- */
-#define        XFS_CALC_WRITEID_LOG_RES(mp) \
-       ((mp)->m_sb.sb_inodesize + 128)
-
 #define        XFS_WRITEID_LOG_RES(mp) ((mp)->m_reservations.tr_swrite)
-
-/*
- * Converting the inode from non-attributed to attributed.
- *     the inode being converted: inode size
- *     agf block and superblock (for block allocation)
- *     the new block (directory sized)
- *     bmap blocks for the new directory block
- *     allocation btrees
- */
-#define        XFS_CALC_ADDAFORK_LOG_RES(mp)   \
-       ((mp)->m_sb.sb_inodesize + \
-        (mp)->m_sb.sb_sectsize * 2 + \
-        (mp)->m_dirblksize + \
-        XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1)) + \
-        XFS_ALLOCFREE_LOG_RES(mp, 1) + \
-        (128 * (4 + (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \
-                XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
-
 #define        XFS_ADDAFORK_LOG_RES(mp)        ((mp)->m_reservations.tr_addafork)
-
-/*
- * Removing the attribute fork of a file
- *    the inode being truncated: inode size
- *    the inode's bmap btree: max depth * block size
- * And the bmap_finish transaction can free the blocks and bmap blocks:
- *    the agf for each of the ags: 4 * sector size
- *    the agfl for each of the ags: 4 * sector size
- *    the super block to reflect the freed blocks: sector size
- *    worst case split in allocation btrees per extent assuming 4 extents:
- *             4 exts * 2 trees * (2 * max depth - 1) * block size
- */
-#define        XFS_CALC_ATTRINVAL_LOG_RES(mp)  \
-       (MAX( \
-        ((mp)->m_sb.sb_inodesize + \
-         XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + \
-         (128 * (1 + XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)))), \
-        ((4 * (mp)->m_sb.sb_sectsize) + \
-         (4 * (mp)->m_sb.sb_sectsize) + \
-         (mp)->m_sb.sb_sectsize + \
-         XFS_ALLOCFREE_LOG_RES(mp, 4) + \
-         (128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))))))
-
 #define        XFS_ATTRINVAL_LOG_RES(mp)       ((mp)->m_reservations.tr_attrinval)
-
-/*
- * Setting an attribute.
- *     the inode getting the attribute
- *     the superblock for allocations
- *     the agfs extents are allocated from
- *     the attribute btree * max depth
- *     the inode allocation btree
- * Since attribute transaction space is dependent on the size of the attribute,
- * the calculation is done partially at mount time and partially at runtime.
- */
-#define        XFS_CALC_ATTRSET_LOG_RES(mp)    \
-       ((mp)->m_sb.sb_inodesize + \
-        (mp)->m_sb.sb_sectsize + \
-         XFS_FSB_TO_B((mp), XFS_DA_NODE_MAXDEPTH) + \
-         (128 * (2 + XFS_DA_NODE_MAXDEPTH)))
-
 #define        XFS_ATTRSET_LOG_RES(mp, ext)    \
        ((mp)->m_reservations.tr_attrset + \
         (ext * (mp)->m_sb.sb_sectsize) + \
         (ext * XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK))) + \
         (128 * (ext + (ext * XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)))))
-
-/*
- * Removing an attribute.
- *    the inode: inode size
- *    the attribute btree could join: max depth * block size
- *    the inode bmap btree could join or split: max depth * block size
- * And the bmap_finish transaction can free the attr blocks freed giving:
- *    the agf for the ag in which the blocks live: 2 * sector size
- *    the agfl for the ag in which the blocks live: 2 * sector size
- *    the superblock for the free block count: sector size
- *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
- */
-#define        XFS_CALC_ATTRRM_LOG_RES(mp)     \
-       (MAX( \
-         ((mp)->m_sb.sb_inodesize + \
-         XFS_FSB_TO_B((mp), XFS_DA_NODE_MAXDEPTH) + \
-         XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + \
-         (128 * (1 + XFS_DA_NODE_MAXDEPTH + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)))), \
-        ((2 * (mp)->m_sb.sb_sectsize) + \
-         (2 * (mp)->m_sb.sb_sectsize) + \
-         (mp)->m_sb.sb_sectsize + \
-         XFS_ALLOCFREE_LOG_RES(mp, 2) + \
-         (128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
-
 #define        XFS_ATTRRM_LOG_RES(mp)  ((mp)->m_reservations.tr_attrrm)
-
-/*
- * Clearing a bad agino number in an agi hash bucket.
- */
-#define        XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp) \
-       ((mp)->m_sb.sb_sectsize + 128)
-
 #define        XFS_CLEAR_AGI_BUCKET_LOG_RES(mp)  ((mp)->m_reservations.tr_clearagi)
 
 
index 785ff101da0a66368a7c06587dd13b3c3eae2f70..2559dfec946bb990afe7e44af28ae43204d6474a 100644 (file)
@@ -62,7 +62,7 @@ xfs_trans_iget(
 {
        int                     error;
 
-       error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp, 0);
+       error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp);
        if (!error && tp)
                xfs_trans_ijoin(tp, *ipp, lock_flags);
        return error;
index 9d376be0ea389ee5b1cacd2f266fe3f44f2a7c2e..c1646838898f45120767046f0b62d43cca92dd54 100644 (file)
@@ -267,7 +267,7 @@ xfs_setattr(
                if (code) {
                        ASSERT(tp == NULL);
                        lock_flags &= ~XFS_ILOCK_EXCL;
-                       ASSERT(lock_flags == XFS_IOLOCK_EXCL);
+                       ASSERT(lock_flags == XFS_IOLOCK_EXCL || !need_iolock);
                        goto error_return;
                }
                tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE);
@@ -1269,7 +1269,7 @@ xfs_lookup(
        if (error)
                goto out;
 
-       error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0);
+       error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp);
        if (error)
                goto out_free_name;
 
index 5958d7845bd5ac86397506bd54e872a262ef6135..17714beb868ef5d17f57fc25323fea915e894ffc 100644 (file)
@@ -212,7 +212,7 @@ char const *acpi_gbl_exception_names_env[] = {
        "AE_NO_GLOBAL_LOCK",
        "AE_ABORT_METHOD",
        "AE_SAME_HANDLER",
-       "AE_WAKE_ONLY_GPE",
+       "AE_NO_HANDLER",
        "AE_OWNER_ID_LIMIT"
 };
 
index 0e4ab1fe5966e09897d51b85e710f784a990c6d8..1371cc997393a83224beb5ff8809e0a22e968b67 100644 (file)
@@ -69,6 +69,7 @@ extern acpi_name acpi_gbl_trace_method_name;
 extern u32 acpi_gbl_trace_flags;
 extern u8 acpi_gbl_enable_aml_debug_object;
 extern u8 acpi_gbl_copy_dsdt_locally;
+extern u8 acpi_gbl_truncate_io_addresses;
 
 extern u32 acpi_current_gpe_count;
 extern struct acpi_table_fadt acpi_gbl_FADT;
index bade172cad47699882db544e7e057e3b35add502..d55f4a7b824db550d3ce2bfbd2c7235859eb08a4 100644 (file)
@@ -663,10 +663,11 @@ typedef u32 acpi_event_status;
 #define ACPI_GPE_MAX                    0xFF
 #define ACPI_NUM_GPE                    256
 
-/* Actions for acpi_set_gpe */
+/* Actions for acpi_set_gpe and acpi_hw_low_set_gpe */
 
 #define ACPI_GPE_ENABLE                 0
 #define ACPI_GPE_DISABLE                1
+#define ACPI_GPE_COND_ENABLE            2
 
 /* gpe_types for acpi_enable_gpe and acpi_disable_gpe */
 
index 04f91c2d3f7b93d88011236b07aa1f71d2a39def..b5043a9890d85a38d4e63d3ae40f546675639e30 100644 (file)
@@ -80,7 +80,7 @@ extern void setup_per_cpu_areas(void);
 
 #ifndef PER_CPU_BASE_SECTION
 #ifdef CONFIG_SMP
-#define PER_CPU_BASE_SECTION ".data.percpu"
+#define PER_CPU_BASE_SECTION ".data..percpu"
 #else
 #define PER_CPU_BASE_SECTION ".data"
 #endif
@@ -92,15 +92,15 @@ extern void setup_per_cpu_areas(void);
 #define PER_CPU_SHARED_ALIGNED_SECTION ""
 #define PER_CPU_ALIGNED_SECTION ""
 #else
-#define PER_CPU_SHARED_ALIGNED_SECTION ".shared_aligned"
-#define PER_CPU_ALIGNED_SECTION ".shared_aligned"
+#define PER_CPU_SHARED_ALIGNED_SECTION "..shared_aligned"
+#define PER_CPU_ALIGNED_SECTION "..shared_aligned"
 #endif
-#define PER_CPU_FIRST_SECTION ".first"
+#define PER_CPU_FIRST_SECTION "..first"
 
 #else
 
 #define PER_CPU_SHARED_ALIGNED_SECTION ""
-#define PER_CPU_ALIGNED_SECTION ".shared_aligned"
+#define PER_CPU_ALIGNED_SECTION "..shared_aligned"
 #define PER_CPU_FIRST_SECTION ""
 
 #endif
index ef779c6fc3d7e89571390a01bbdb3da137bc1af1..48c5299cbf26e796e3188f397faa96cd3889a112 100644 (file)
 #define NOSAVE_DATA                                                    \
        . = ALIGN(PAGE_SIZE);                                           \
        VMLINUX_SYMBOL(__nosave_begin) = .;                             \
-       *(.data.nosave)                                                 \
+       *(.data..nosave)                                                \
        . = ALIGN(PAGE_SIZE);                                           \
        VMLINUX_SYMBOL(__nosave_end) = .;
 
 #define PAGE_ALIGNED_DATA(page_align)                                  \
        . = ALIGN(page_align);                                          \
-       *(.data.page_aligned)
+       *(.data..page_aligned)
 
 #define READ_MOSTLY_DATA(align)                                                \
        . = ALIGN(align);                                               \
-       *(.data.read_mostly)
+       *(.data..read_mostly)
 
 #define CACHELINE_ALIGNED_DATA(align)                                  \
        . = ALIGN(align);                                               \
-       *(.data.cacheline_aligned)
+       *(.data..cacheline_aligned)
 
 #define INIT_TASK_DATA(align)                                          \
        . = ALIGN(align);                                               \
-       *(.data.init_task)
+       *(.data..init_task)
 
 /*
  * Read only Data
  */
 #define INIT_TASK_DATA_SECTION(align)                                  \
        . = ALIGN(align);                                               \
-       .data.init_task : {                                             \
+       .data..init_task : {                                            \
                INIT_TASK_DATA(align)                                   \
        }
 
 #define BSS(bss_align)                                                 \
        . = ALIGN(bss_align);                                           \
        .bss : AT(ADDR(.bss) - LOAD_OFFSET) {                           \
-               *(.bss.page_aligned)                                    \
+               *(.bss..page_aligned)                                   \
                *(.dynbss)                                              \
                *(.bss)                                                 \
                *(COMMON)                                               \
  */
 #define PERCPU_VADDR(vaddr, phdr)                                      \
        VMLINUX_SYMBOL(__per_cpu_load) = .;                             \
-       .data.percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load)          \
+       .data..percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load)         \
                                - LOAD_OFFSET) {                        \
                VMLINUX_SYMBOL(__per_cpu_start) = .;                    \
-               *(.data.percpu.first)                                   \
-               *(.data.percpu.page_aligned)                            \
-               *(.data.percpu)                                         \
-               *(.data.percpu.shared_aligned)                          \
+               *(.data..percpu..first)                                 \
+               *(.data..percpu..page_aligned)                          \
+               *(.data..percpu)                                        \
+               *(.data..percpu..shared_aligned)                        \
                VMLINUX_SYMBOL(__per_cpu_end) = .;                      \
        } phdr                                                          \
-       . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data.percpu);
+       . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data..percpu);
 
 /**
  * PERCPU - define output section for percpu area, simple version
  *
  * This macro is equivalent to ALIGN(align); PERCPU_VADDR( , ) except
  * that __per_cpu_load is defined as a relative symbol against
- * .data.percpu which is required for relocatable x86_32
+ * .data..percpu which is required for relocatable x86_32
  * configuration.
  */
 #define PERCPU(align)                                                  \
        . = ALIGN(align);                                               \
-       .data.percpu    : AT(ADDR(.data.percpu) - LOAD_OFFSET) {        \
+       .data..percpu   : AT(ADDR(.data..percpu) - LOAD_OFFSET) {       \
                VMLINUX_SYMBOL(__per_cpu_load) = .;                     \
                VMLINUX_SYMBOL(__per_cpu_start) = .;                    \
-               *(.data.percpu.first)                                   \
-               *(.data.percpu.page_aligned)                            \
-               *(.data.percpu)                                         \
-               *(.data.percpu.shared_aligned)                          \
+               *(.data..percpu..first)                                 \
+               *(.data..percpu..page_aligned)                          \
+               *(.data..percpu)                                        \
+               *(.data..percpu..shared_aligned)                        \
                VMLINUX_SYMBOL(__per_cpu_end) = .;                      \
        }
 
index dc5873c21e4566ceaf6628882abae905098763f9..1121f7799c6ff527838ec50052d51bc10b10e2e7 100644 (file)
@@ -130,4 +130,7 @@ extern int drm_helper_resume_force_mode(struct drm_device *dev);
 extern void drm_kms_helper_poll_init(struct drm_device *dev);
 extern void drm_kms_helper_poll_fini(struct drm_device *dev);
 extern void drm_helper_hpd_irq_event(struct drm_device *dev);
+
+extern void drm_kms_helper_poll_disable(struct drm_device *dev);
+extern void drm_kms_helper_poll_enable(struct drm_device *dev);
 #endif
index b64a8d7cdf6d291205f8b89edf3a78d4a6a4d9c6..7f0028e1010b97e253b29dffdaaa8edb152bab54 100644 (file)
@@ -275,6 +275,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_OVERLAY           7
 #define I915_PARAM_HAS_PAGEFLIPPING     8
 #define I915_PARAM_HAS_EXECBUF2          9
+#define I915_PARAM_HAS_BSD              10
 
 typedef struct drm_i915_getparam {
        int param;
@@ -616,7 +617,9 @@ struct drm_i915_gem_execbuffer2 {
        __u32 num_cliprects;
        /** This is a struct drm_clip_rect *cliprects */
        __u64 cliprects_ptr;
-       __u64 flags; /* currently unused */
+#define I915_EXEC_RENDER                 (1<<0)
+#define I915_EXEC_BSD                    (1<<1)
+       __u64 flags;
        __u64 rsvd1;
        __u64 rsvd2;
 };
index a6a9f4af5ebd8257d92dcd592551b6fb05f91931..fe917dee723a7357f44c285626189ae7acd5e863 100644 (file)
@@ -79,6 +79,7 @@ struct drm_nouveau_gpuobj_free {
 #define NOUVEAU_GETPARAM_CHIPSET_ID      11
 #define NOUVEAU_GETPARAM_VM_VRAM_BASE    12
 #define NOUVEAU_GETPARAM_GRAPH_UNITS     13
+#define NOUVEAU_GETPARAM_PTIMER_TIME     14
 struct drm_nouveau_getparam {
        uint64_t param;
        uint64_t value;
index 3ff9fc071dfee1eff45bda07e5ba208af3666c46..5347063e9d5a52b6896c135af389f6fcf8425ff3 100644 (file)
@@ -903,6 +903,7 @@ struct drm_radeon_cs {
 #define RADEON_INFO_NUM_Z_PIPES        0x02
 #define RADEON_INFO_ACCEL_WORKING      0x03
 #define RADEON_INFO_CRTC_FROM_ID       0x04
+#define RADEON_INFO_ACCEL_WORKING2     0x05
 
 struct drm_radeon_info {
        uint32_t                request;
index c7645f480d1219cb84c765e5962d86cdd470ec54..4d0842391edc666f8985329fed245b989e3a0c2d 100644 (file)
@@ -50,6 +50,8 @@
 #define DRM_VMW_EXECBUF              12
 #define DRM_VMW_FIFO_DEBUG           13
 #define DRM_VMW_FENCE_WAIT           14
+/* guarded by minor version >= 2 */
+#define DRM_VMW_UPDATE_LAYOUT        15
 
 
 /*************************************************************************/
@@ -585,4 +587,28 @@ struct drm_vmw_stream_arg {
  * sure that the stream has been stopped.
  */
 
+/*************************************************************************/
+/**
+ * DRM_VMW_UPDATE_LAYOUT - Update layout
+ *
+ * Updates the prefered modes and connection status for connectors. The
+ * command conisits of one drm_vmw_update_layout_arg pointing out a array
+ * of num_outputs drm_vmw_rect's.
+ */
+
+/**
+ * struct drm_vmw_update_layout_arg
+ *
+ * @num_outputs: number of active
+ * @rects: pointer to array of drm_vmw_rect
+ *
+ * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
+ */
+
+struct drm_vmw_update_layout_arg {
+       uint32_t num_outputs;
+       uint32_t pad64;
+       uint64_t rects;
+};
+
 #endif
index 9101ed64f803c64d3158df9aa134d8d4ffd26789..09ea4a1e95058ec4c73a20204c2bdbd8e1895388 100644 (file)
@@ -79,7 +79,6 @@ struct agp_memory {
        u32 physical;
        bool is_bound;
        bool is_flushed;
-       bool vmalloc_flag;
        /* list of agp_memory mapped to the aperture */
        struct list_head mapped_list;
        /* DMA-mapped addresses */
index e6e0cb5437e6ce6d00a7fcebe7756b9fdac92480..9ae2889096b695cbeb7dfbc086ed4bb7484c1c40 100644 (file)
@@ -105,8 +105,8 @@ int bdi_register(struct backing_dev_info *bdi, struct device *parent,
 int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
 void bdi_unregister(struct backing_dev_info *bdi);
 int bdi_setup_and_register(struct backing_dev_info *, char *, unsigned int);
-void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
-                               long nr_pages, int sb_locked);
+void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages);
+void bdi_start_background_writeback(struct backing_dev_info *bdi);
 int bdi_writeback_task(struct bdi_writeback *wb);
 int bdi_has_dirty_io(struct backing_dev_info *bdi);
 void bdi_arm_supers_timer(void);
index 8b7f5e0914add2b751346224270a9e297d89f5c9..09a840264d6fdf54b0170970eb9c3c49acc9def6 100644 (file)
@@ -1211,14 +1211,23 @@ struct work_struct;
 int kblockd_schedule_work(struct request_queue *q, struct work_struct *work);
 
 #ifdef CONFIG_BLK_CGROUP
+/*
+ * This should not be using sched_clock(). A real patch is in progress
+ * to fix this up, until that is in place we need to disable preemption
+ * around sched_clock() in this function and set_io_start_time_ns().
+ */
 static inline void set_start_time_ns(struct request *req)
 {
+       preempt_disable();
        req->start_time_ns = sched_clock();
+       preempt_enable();
 }
 
 static inline void set_io_start_time_ns(struct request *req)
 {
+       preempt_disable();
        req->io_start_time_ns = sched_clock();
+       preempt_enable();
 }
 
 static inline uint64_t rq_start_time_ns(struct request *req)
index 97e24881c4c6f477496130c982e1962e770df9eb..4c570653ab84f9822ba9e1e1f19a41242c16b74f 100644 (file)
@@ -31,7 +31,7 @@
 #ifndef __cacheline_aligned
 #define __cacheline_aligned                                    \
   __attribute__((__aligned__(SMP_CACHE_BYTES),                 \
-                __section__(".data.cacheline_aligned")))
+                __section__(".data..cacheline_aligned")))
 #endif /* __cacheline_aligned */
 
 #ifndef __cacheline_aligned_in_smp
index 0c621604baa1d7ff8185029d4eaade8ccad82d64..e3d00fdb858dc3cbf7e35b7d75a93b9c4b7321f3 100644 (file)
@@ -525,13 +525,21 @@ static inline struct cgroup_subsys_state *cgroup_subsys_state(
        return cgrp->subsys[subsys_id];
 }
 
-static inline struct cgroup_subsys_state *task_subsys_state(
-       struct task_struct *task, int subsys_id)
+/*
+ * function to get the cgroup_subsys_state which allows for extra
+ * rcu_dereference_check() conditions, such as locks used during the
+ * cgroup_subsys::attach() methods.
+ */
+#define task_subsys_state_check(task, subsys_id, __c)                  \
+       rcu_dereference_check(task->cgroups->subsys[subsys_id],         \
+                             rcu_read_lock_held() ||                   \
+                             lockdep_is_held(&task->alloc_lock) ||     \
+                             cgroup_lock_is_held() || (__c))
+
+static inline struct cgroup_subsys_state *
+task_subsys_state(struct task_struct *task, int subsys_id)
 {
-       return rcu_dereference_check(task->cgroups->subsys[subsys_id],
-                                    rcu_read_lock_held() ||
-                                    lockdep_is_held(&task->alloc_lock) ||
-                                    cgroup_lock_is_held());
+       return task_subsys_state_check(task, subsys_id, false);
 }
 
 static inline struct cgroup* task_cgroup(struct task_struct *task,
index 73dcf804bc940e6738f5f0f553f3cf2045f78fd7..0da5b187f1245e8c33fd659420f5e4dca82b9ead 100644 (file)
  * naked functions because then mcount is called without stack and frame pointer
  * being set up and there is no chance to restore the lr register to the value
  * before mcount was called.
+ *
+ * The asm() bodies of naked functions often depend on standard calling conventions,
+ * therefore they must be noinline and noclone.  GCC 4.[56] currently fail to enforce
+ * this, so we must do so ourselves.  See GCC PR44290.
  */
-#define __naked                                __attribute__((naked)) notrace
+#define __naked                                __attribute__((naked)) noinline __noclone notrace
 
 #define __noreturn                     __attribute__((noreturn))
 
@@ -85,3 +89,7 @@
 #define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
 #define gcc_header(x) _gcc_header(x)
 #include gcc_header(__GNUC__)
+
+#if !defined(__noclone)
+#define __noclone      /* not needed */
+#endif
index 94dea3ffbfa19576e2cd8bb59b56658465101b49..fcfa5b9a4317af2b272d06073d7af51019ebf321 100644 (file)
  * unreleased.  Really, we need to have autoconf for the kernel.
  */
 #define unreachable() __builtin_unreachable()
+
+/* Mark a function definition as prohibited from being cloned. */
+#define __noclone      __attribute__((__noclone__))
+
 #endif
 
 #endif
index 68530521ad0056edcda138183f8246b625b24c3f..b8d2516668aa067d43d7c6c6e5301f3688469658 100644 (file)
@@ -53,7 +53,7 @@
 
 
 extern const char *drbd_buildtag(void);
-#define REL_VERSION "8.3.8rc1"
+#define REL_VERSION "8.3.8"
 #define API_VERSION 88
 #define PRO_VERSION_MIN 86
 #define PRO_VERSION_MAX 94
index b3cd4de9432b68007342098ad7dbb662cbc1fce0..52c0da4bdd18fe5969fbf9c583652c0f7f00ba07 100644 (file)
@@ -40,7 +40,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
                                const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
-extern int ddebug_remove_module(char *mod_name);
+extern int ddebug_remove_module(const char *mod_name);
 
 #define __dynamic_dbg_enabled(dd)  ({       \
        int __ret = 0;                                                       \
@@ -73,7 +73,7 @@ extern int ddebug_remove_module(char *mod_name);
 
 #else
 
-static inline int ddebug_remove_module(char *mod)
+static inline int ddebug_remove_module(const char *mod)
 {
        return 0;
 }
diff --git a/include/linux/edac_mce.h b/include/linux/edac_mce.h
new file mode 100644 (file)
index 0000000..f974fc0
--- /dev/null
@@ -0,0 +1,31 @@
+/* Provides edac interface to mcelog events
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License version 2.
+ *
+ * Copyright (c) 2009 by:
+ *      Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * Red Hat Inc. http://www.redhat.com
+ */
+
+#if defined(CONFIG_EDAC_MCE) || \
+                       (defined(CONFIG_EDAC_MCE_MODULE) && defined(MODULE))
+
+#include <asm/mce.h>
+#include <linux/list.h>
+
+struct edac_mce {
+       struct list_head list;
+
+       void *priv;
+       int (*check_error)(void *priv, struct mce *mce);
+};
+
+int edac_mce_register(struct edac_mce *edac_mce);
+void edac_mce_unregister(struct edac_mce *edac_mce);
+int edac_mce_parse(struct mce *mce);
+
+#else
+#define edac_mce_parse(mce) (0)
+#endif
index 907ace3a64c8abef33aff5a1d7e3bc3c72337a54..8e5a9dfb76bf6425934a09427b8f16df82e937be 100644 (file)
@@ -786,8 +786,6 @@ struct fb_tile_ops {
 #define FBINFO_MISC_USEREVENT          0x10000 /* event request
                                                  from userspace */
 #define FBINFO_MISC_TILEBLITTING       0x20000 /* use tile blitting */
-#define FBINFO_MISC_FIRMWARE           0x40000 /* a replaceable firmware
-                                                 inited framebuffer */
 
 /* A driver may set this flag to indicate that it does want a set_par to be
  * called every time when fbcon_switch is executed. The advantage is that with
@@ -801,6 +799,8 @@ struct fb_tile_ops {
  */
 #define FBINFO_MISC_ALWAYS_SETPAR   0x40000
 
+/* where the fb is a firmware driver, and can be replaced with a proper one */
+#define FBINFO_MISC_FIRMWARE        0x80000
 /*
  * Host and GPU endianness differ.
  */
index 3428393942a642f877dc065d86c05044305af399..471e1ff5079a0329bc01d03ad45ca20afb6186be 100644 (file)
@@ -2388,7 +2388,7 @@ extern const struct file_operations simple_dir_operations;
 extern const struct inode_operations simple_dir_inode_operations;
 struct tree_descr { char *name; const struct file_operations *ops; int mode; };
 struct dentry *d_alloc_name(struct dentry *, const char *);
-extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
+extern int simple_fill_super(struct super_block *, unsigned long, struct tree_descr *);
 extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
 extern void simple_release_fs(struct vfsmount **mount, int *count);
 
index ab1d31f9352bbcefb46369667c145c3615b29a2c..de994304e0bbb2a1e21e5d6dd7a59ebeea1ebd71 100644 (file)
@@ -301,7 +301,7 @@ void __init parse_early_options(char *cmdline);
 #endif
 
 /* Data marked not to be saved by software suspend */
-#define __nosavedata __section(.data.nosave)
+#define __nosavedata __section(.data..nosave)
 
 /* This means "can be init if no module support, otherwise module load
    may call it." */
index 2beaa13492beb5dffdb90c0041d942a3785181e1..1f43fa56f6001f821736e4b66e9fac5e6e0375ed 100644 (file)
@@ -183,7 +183,7 @@ extern struct cred init_cred;
 }
 
 /* Attach to the init_task data structure for proper alignment */
-#define __init_task_data __attribute__((__section__(".data.init_task")))
+#define __init_task_data __attribute__((__section__(".data..init_task")))
 
 
 #endif
index a0bb301afac0812998370e6af2a778b08f14dc1c..64d5291330312ac718ba7f649e3d428063127f39 100644 (file)
@@ -7,7 +7,6 @@
 struct cfq_queue;
 struct cfq_io_context {
        void *key;
-       unsigned long dead_key;
 
        struct cfq_queue *cfqq[2];
 
index 3bad2701bfa6349ff9ff8e0314f2b6cb3985e1f2..b85f3ff34d7d3d71cb99f0ded4db0ce186780b57 100644 (file)
@@ -1023,6 +1023,7 @@ extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
 extern int ata_std_bios_param(struct scsi_device *sdev,
                              struct block_device *bdev,
                              sector_t capacity, int geom[]);
+extern void ata_scsi_unlock_native_capacity(struct scsi_device *sdev);
 extern int ata_scsi_slave_config(struct scsi_device *sdev);
 extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
 extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
@@ -1174,6 +1175,7 @@ extern struct device_attribute *ata_common_sdev_attrs[];
        .slave_configure        = ata_scsi_slave_config,        \
        .slave_destroy          = ata_scsi_slave_destroy,       \
        .bios_param             = ata_std_bios_param,           \
+       .unlock_native_capacity = ata_scsi_unlock_native_capacity, \
        .sdev_attrs             = ata_common_sdev_attrs
 
 #define ATA_NCQ_SHT(drv_name)                                  \
index 5126cceb6ae97c7d401f197497f0a1311e55fe6f..7135ebc8428c5273fd62535b985e1fb00e9bfbe0 100644 (file)
@@ -18,8 +18,8 @@
 # define asmregparm
 #endif
 
-#define __page_aligned_data    __section(.data.page_aligned) __aligned(PAGE_SIZE)
-#define __page_aligned_bss     __section(.bss.page_aligned) __aligned(PAGE_SIZE)
+#define __page_aligned_data    __section(.data..page_aligned) __aligned(PAGE_SIZE)
+#define __page_aligned_bss     __section(.bss..page_aligned) __aligned(PAGE_SIZE)
 
 /*
  * For assembly routines.
@@ -27,8 +27,8 @@
  * Note when using these that you must specify the appropriate
  * alignment directives yourself
  */
-#define __PAGE_ALIGNED_DATA    .section ".data.page_aligned", "aw"
-#define __PAGE_ALIGNED_BSS     .section ".bss.page_aligned", "aw"
+#define __PAGE_ALIGNED_DATA    .section ".data..page_aligned", "aw"
+#define __PAGE_ALIGNED_BSS     .section ".bss..page_aligned", "aw"
 
 /*
  * This is used by architectures to keep arguments on the stack
index 8392884a2977cda6a5f004fed2511ad51a140aa5..5d57a3a1fa1b1b9143a5e80381ac7668b51bb677 100644 (file)
@@ -544,6 +544,21 @@ static inline void list_splice_tail_init(struct list_head *list,
             &pos->member != (head);                                    \
             pos = n, n = list_entry(n->member.prev, typeof(*n), member))
 
+/**
+ * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
+ * @pos:       the loop cursor used in the list_for_each_entry_safe loop
+ * @n:         temporary storage used in list_for_each_entry_safe
+ * @member:    the name of the list_struct within the struct.
+ *
+ * list_safe_reset_next is not safe to use in general if the list may be
+ * modified concurrently (eg. the lock is dropped in the loop body). An
+ * exception to this is if the cursor element (pos) is pinned in the list,
+ * and list_safe_reset_next is called after re-taking the lock and before
+ * completing the current iteration of the loop body.
+ */
+#define list_safe_reset_next(pos, n, member)                           \
+       n = list_entry(pos->member.next, typeof(*pos), member)
+
 /*
  * Double linked lists with a single pointer list head.
  * Mostly useful for hash tables where the two pointer list head is
index b631c46cffd9c4fe52cf7c5bb5a5db7c88223d0a..f6c9b7dcb9fdd77ccf7410e07fb5d89960d26453 100644 (file)
@@ -3,6 +3,12 @@
 #include <linux/module.h>
 #include <linux/major.h>
 
+/*
+ *     These allocations are managed by device@lanana.org. If you use an
+ *     entry that is not in assigned your entry may well be moved and
+ *     reassigned, or set dynamic if a fixed value is not justified.
+ */
+
 #define PSMOUSE_MINOR          1
 #define MS_BUSMOUSE_MINOR      2
 #define ATIXL_BUSMOUSE_MINOR   3
@@ -30,7 +36,6 @@
 #define HPET_MINOR             228
 #define FUSE_MINOR             229
 #define KVM_MINOR              232
-#define VHOST_NET_MINOR                233
 #define BTRFS_MINOR            234
 #define AUTOFS_MINOR           235
 #define MISC_DYNAMIC_MINOR     255
index aafe832f18aa276f6fc45019ed4ec3f7cc22caf8..d4a2ebbdab4b2ad3f8adb4bec89aada45e0ff7fc 100644 (file)
@@ -14,6 +14,9 @@
 #ifndef __SH_MMCIF_H__
 #define __SH_MMCIF_H__
 
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
 /*
  * MMCIF : CE_CLK_CTRL [19:16]
  * 1000 : Peripheral clock / 512
@@ -36,4 +39,162 @@ struct sh_mmcif_plat_data {
        u32     ocr;
 };
 
+#define MMCIF_CE_CMD_SET       0x00000000
+#define MMCIF_CE_ARG           0x00000008
+#define MMCIF_CE_ARG_CMD12     0x0000000C
+#define MMCIF_CE_CMD_CTRL      0x00000010
+#define MMCIF_CE_BLOCK_SET     0x00000014
+#define MMCIF_CE_CLK_CTRL      0x00000018
+#define MMCIF_CE_BUF_ACC       0x0000001C
+#define MMCIF_CE_RESP3         0x00000020
+#define MMCIF_CE_RESP2         0x00000024
+#define MMCIF_CE_RESP1         0x00000028
+#define MMCIF_CE_RESP0         0x0000002C
+#define MMCIF_CE_RESP_CMD12    0x00000030
+#define MMCIF_CE_DATA          0x00000034
+#define MMCIF_CE_INT           0x00000040
+#define MMCIF_CE_INT_MASK      0x00000044
+#define MMCIF_CE_HOST_STS1     0x00000048
+#define MMCIF_CE_HOST_STS2     0x0000004C
+#define MMCIF_CE_VERSION       0x0000007C
+
+extern inline u32 sh_mmcif_readl(void __iomem *addr, int reg)
+{
+       return readl(addr + reg);
+}
+
+extern inline void sh_mmcif_writel(void __iomem *addr, int reg, u32 val)
+{
+       writel(val, addr + reg);
+}
+
+#define SH_MMCIF_BBS 512 /* boot block size */
+
+extern inline void sh_mmcif_boot_cmd_send(void __iomem *base,
+                                         unsigned long cmd, unsigned long arg)
+{
+       sh_mmcif_writel(base, MMCIF_CE_INT, 0);
+       sh_mmcif_writel(base, MMCIF_CE_ARG, arg);
+       sh_mmcif_writel(base, MMCIF_CE_CMD_SET, cmd);
+}
+
+extern inline int sh_mmcif_boot_cmd_poll(void __iomem *base, unsigned long mask)
+{
+       unsigned long tmp;
+       int cnt;
+
+       for (cnt = 0; cnt < 1000000; cnt++) {
+               tmp = sh_mmcif_readl(base, MMCIF_CE_INT);
+               if (tmp & mask) {
+                       sh_mmcif_writel(base, MMCIF_CE_INT, tmp & ~mask);
+                       return 0;
+               }
+       }
+
+       return -1;
+}
+
+extern inline int sh_mmcif_boot_cmd(void __iomem *base,
+                                   unsigned long cmd, unsigned long arg)
+{
+       sh_mmcif_boot_cmd_send(base, cmd, arg);
+       return sh_mmcif_boot_cmd_poll(base, 0x00010000);
+}
+
+extern inline int sh_mmcif_boot_do_read_single(void __iomem *base,
+                                              unsigned int block_nr,
+                                              unsigned long *buf)
+{
+       int k;
+
+       /* CMD13 - Status */
+       sh_mmcif_boot_cmd(base, 0x0d400000, 0x00010000);
+
+       if (sh_mmcif_readl(base, MMCIF_CE_RESP0) != 0x0900)
+               return -1;
+
+       /* CMD17 - Read */
+       sh_mmcif_boot_cmd(base, 0x11480000, block_nr * SH_MMCIF_BBS);
+       if (sh_mmcif_boot_cmd_poll(base, 0x00100000) < 0)
+               return -1;
+
+       for (k = 0; k < (SH_MMCIF_BBS / 4); k++)
+               buf[k] = sh_mmcif_readl(base, MMCIF_CE_DATA);
+
+       return 0;
+}
+
+extern inline int sh_mmcif_boot_do_read(void __iomem *base,
+                                       unsigned long first_block,
+                                       unsigned long nr_blocks,
+                                       void *buf)
+{
+       unsigned long k;
+       int ret = 0;
+
+       /* CMD16 - Set the block size */
+       sh_mmcif_boot_cmd(base, 0x10400000, SH_MMCIF_BBS);
+
+       for (k = 0; !ret && k < nr_blocks; k++)
+               ret = sh_mmcif_boot_do_read_single(base, first_block + k,
+                                                  buf + (k * SH_MMCIF_BBS));
+
+       return ret;
+}
+
+extern inline void sh_mmcif_boot_init(void __iomem *base)
+{
+       unsigned long tmp;
+
+       /* reset */
+       tmp = sh_mmcif_readl(base, MMCIF_CE_VERSION);
+       sh_mmcif_writel(base, MMCIF_CE_VERSION, tmp | 0x80000000);
+       sh_mmcif_writel(base, MMCIF_CE_VERSION, tmp & ~0x80000000);
+
+       /* byte swap */
+       sh_mmcif_writel(base, MMCIF_CE_BUF_ACC, 0x00010000);
+
+       /* Set block size in MMCIF hardware */
+       sh_mmcif_writel(base, MMCIF_CE_BLOCK_SET, SH_MMCIF_BBS);
+
+       /* Enable the clock, set it to Bus clock/256 (about 325Khz)*/
+       sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 0x01072fff);
+
+       /* CMD0 */
+       sh_mmcif_boot_cmd(base, 0x00000040, 0);
+
+       /* CMD1 - Get OCR */
+       do {
+               sh_mmcif_boot_cmd(base, 0x01405040, 0x40300000); /* CMD1 */
+       } while ((sh_mmcif_readl(base, MMCIF_CE_RESP0) & 0x80000000)
+                != 0x80000000);
+
+       /* CMD2 - Get CID */
+       sh_mmcif_boot_cmd(base, 0x02806040, 0);
+
+       /* CMD3 - Set card relative address */
+       sh_mmcif_boot_cmd(base, 0x03400040, 0x00010000);
+}
+
+extern inline void sh_mmcif_boot_slurp(void __iomem *base,
+                                      unsigned char *buf,
+                                      unsigned long no_bytes)
+{
+       unsigned long tmp;
+
+       /* In data transfer mode: Set clock to Bus clock/4 (about 20Mhz) */
+       sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 0x01012fff);
+
+       /* CMD9 - Get CSD */
+       sh_mmcif_boot_cmd(base, 0x09806000, 0x00010000);
+
+       /* CMD7 - Select the card */
+       sh_mmcif_boot_cmd(base, 0x07400000, 0x00010000);
+
+       tmp = no_bytes / SH_MMCIF_BBS;
+       tmp += (no_bytes % SH_MMCIF_BBS) ? 1 : 0;
+
+       sh_mmcif_boot_do_read(base, 512, tmp, buf);
+}
+
 #endif /* __SH_MMCIF_H__ */
index 6914fcad46733974df83c76c5d7e2d96008793be..8a6b9fdc7ffae0c20335b8a2c73726396a934ee2 100644 (file)
@@ -181,6 +181,13 @@ void *__symbol_get(const char *symbol);
 void *__symbol_get_gpl(const char *symbol);
 #define symbol_get(x) ((typeof(&x))(__symbol_get(MODULE_SYMBOL_PREFIX #x)))
 
+/* modules using other modules: kdb wants to see this. */
+struct module_use {
+       struct list_head source_list;
+       struct list_head target_list;
+       struct module *source, *target;
+};
+
 #ifndef __GENKSYMS__
 #ifdef CONFIG_MODVERSIONS
 /* Mark the CRC weak since genksyms apparently decides not to
@@ -359,7 +366,9 @@ struct module
 
 #ifdef CONFIG_MODULE_UNLOAD
        /* What modules depend on me? */
-       struct list_head modules_which_use_me;
+       struct list_head source_list;
+       /* What modules do I depend on? */
+       struct list_head target_list;
 
        /* Who is waiting for us to be unloaded */
        struct task_struct *waiter;
@@ -663,43 +672,10 @@ static inline int module_get_iter_tracepoints(struct tracepoint_iter *iter)
 
 #endif /* CONFIG_MODULES */
 
-struct device_driver;
 #ifdef CONFIG_SYSFS
-struct module;
-
 extern struct kset *module_kset;
 extern struct kobj_type module_ktype;
 extern int module_sysfs_initialized;
-
-int mod_sysfs_init(struct module *mod);
-int mod_sysfs_setup(struct module *mod,
-                          struct kernel_param *kparam,
-                          unsigned int num_params);
-int module_add_modinfo_attrs(struct module *mod);
-void module_remove_modinfo_attrs(struct module *mod);
-
-#else /* !CONFIG_SYSFS */
-
-static inline int mod_sysfs_init(struct module *mod)
-{
-       return 0;
-}
-
-static inline int mod_sysfs_setup(struct module *mod,
-                          struct kernel_param *kparam,
-                          unsigned int num_params)
-{
-       return 0;
-}
-
-static inline int module_add_modinfo_attrs(struct module *mod)
-{
-       return 0;
-}
-
-static inline void module_remove_modinfo_attrs(struct module *mod)
-{ }
-
 #endif /* CONFIG_SYSFS */
 
 #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
index c00cc0c4d0b7c29614bbafdfabe73828a04a0fbd..24e5d01d27d07b860bfed06701fb2d864ee89bc3 100644 (file)
@@ -397,7 +397,7 @@ struct xt_table_info {
         * @stacksize jumps (number of user chains) can possibly be made.
         */
        unsigned int stacksize;
-       unsigned int *stackptr;
+       unsigned int __percpu *stackptr;
        void ***jumpstack;
        /* ipt_entry tables: one per CPU */
        /* Note : this field MUST be the last one, see XT_TABLE_INFO_SZ */
index 6a471aba3b07aced498219d4e39498e6d577bfc0..7cb00845f150ca185b73a47931c6a1fbcd4c1cef 100644 (file)
@@ -632,6 +632,7 @@ void pci_fixup_cardbus(struct pci_bus *);
 
 /* Generic PCI functions used internally */
 
+void pcibios_scan_specific_bus(int busn);
 extern struct pci_bus *pci_find_bus(int domain, int busnr);
 void pci_bus_add_devices(const struct pci_bus *bus);
 struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus,
index ae66851870becb2e496d7994f7a11a548aac16d8..3bedcc149c843bfec71e29c2b6e319a4d052c70b 100644 (file)
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE       0x0759
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS     0x07D8
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS     0x0AA2
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA     0x0D85
 
 #define PCI_VENDOR_ID_IMS              0x10e0
 #define PCI_DEVICE_ID_IMS_TT128                0x9128
 #define PCI_VENDOR_ID_JMICRON          0x197B
 #define PCI_DEVICE_ID_JMICRON_JMB360   0x2360
 #define PCI_DEVICE_ID_JMICRON_JMB361   0x2361
+#define PCI_DEVICE_ID_JMICRON_JMB362   0x2362
 #define PCI_DEVICE_ID_JMICRON_JMB363   0x2363
 #define PCI_DEVICE_ID_JMICRON_JMB365   0x2365
 #define PCI_DEVICE_ID_JMICRON_JMB366   0x2366
 #define PCI_DEVICE_ID_INTEL_ICH9_6     0x2930
 #define PCI_DEVICE_ID_INTEL_ICH9_7     0x2916
 #define PCI_DEVICE_ID_INTEL_ICH9_8     0x2918
+#define PCI_DEVICE_ID_INTEL_I7_MCR     0x2c18
+#define PCI_DEVICE_ID_INTEL_I7_MC_TAD  0x2c19
+#define PCI_DEVICE_ID_INTEL_I7_MC_RAS  0x2c1a
+#define PCI_DEVICE_ID_INTEL_I7_MC_TEST 0x2c1c
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL  0x2c20
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR  0x2c21
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK  0x2c22
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC    0x2c23
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL  0x2c28
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR  0x2c29
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK  0x2c2a
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC    0x2c2b
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL  0x2c30
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR  0x2c31
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK  0x2c32
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC    0x2c33
+#define PCI_DEVICE_ID_INTEL_I7_NONCORE 0x2c41
+#define PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT 0x2c40
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE     0x2c50
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT 0x2c51
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2 0x2c70
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_SAD         0x2c81
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0   0x2c90
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_PHY0    0x2c91
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR         0x2c98
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD      0x2c99
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST     0x2c9C
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL 0x2ca0
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR 0x2ca1
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK 0x2ca2
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC   0x2ca3
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL 0x2ca8
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR 0x2ca9
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK 0x2caa
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC   0x2cab
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR_REV2          0x2d98
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD_REV2       0x2d99
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_RAS_REV2       0x2d9a
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST_REV2      0x2d9c
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL_REV2  0x2da0
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR_REV2  0x2da1
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK_REV2  0x2da2
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC_REV2    0x2da3
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL_REV2  0x2da8
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR_REV2  0x2da9
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK_REV2  0x2daa
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC_REV2    0x2dab
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_CTRL_REV2  0x2db0
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2  0x2db1
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2  0x2db2
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2    0x2db3
 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
 #define PCI_DEVICE_ID_INTEL_IOAT_TBG4  0x3429
 #define PCI_DEVICE_ID_INTEL_IOAT_TBG5  0x342a
 #define PCI_DEVICE_ID_INTEL_IOAT_TBG6  0x342b
 #define PCI_DEVICE_ID_INTEL_IOAT_TBG7  0x342c
+#define PCI_DEVICE_ID_INTEL_X58_HUB_MGMT 0x342e
 #define PCI_DEVICE_ID_INTEL_IOAT_TBG0  0x3430
 #define PCI_DEVICE_ID_INTEL_IOAT_TBG1  0x3431
 #define PCI_DEVICE_ID_INTEL_IOAT_TBG2  0x3432
index 68567c0b3a5d4d29cb5006d42ad3ad38d178e291..ce2dc655cd1d40a6765acc2dd3f49e104bca4f5c 100644 (file)
  * Declaration/definition used for per-CPU variables that must be page aligned.
  */
 #define DECLARE_PER_CPU_PAGE_ALIGNED(type, name)                       \
-       DECLARE_PER_CPU_SECTION(type, name, ".page_aligned")            \
+       DECLARE_PER_CPU_SECTION(type, name, "..page_aligned")           \
        __aligned(PAGE_SIZE)
 
 #define DEFINE_PER_CPU_PAGE_ALIGNED(type, name)                                \
-       DEFINE_PER_CPU_SECTION(type, name, ".page_aligned")             \
+       DEFINE_PER_CPU_SECTION(type, name, "..page_aligned")            \
        __aligned(PAGE_SIZE)
 
 /*
index 126120819a0dba4aeb931094094c27d3d80f9aa0..eec3bae164d451a38b23906a283af54965074ec0 100644 (file)
@@ -12,7 +12,7 @@ struct pt_regs;
 
 extern int             register_exec_domain(struct exec_domain *);
 extern int             unregister_exec_domain(struct exec_domain *);
-extern int             __set_personality(unsigned long);
+extern int             __set_personality(unsigned int);
 
 #endif /* __KERNEL__ */
 
index 16de3933c45ed32b6c4e51a00514f00fe1667d97..445796945ac9d1c491c1d740f0f2ca7bfa1ae22b 100644 (file)
@@ -139,7 +139,9 @@ void pipe_lock(struct pipe_inode_info *);
 void pipe_unlock(struct pipe_inode_info *);
 void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
 
-extern unsigned int pipe_max_pages;
+extern unsigned int pipe_max_size, pipe_min_size;
+int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
+
 
 /* Drop the inode semaphore and wait for a pipe event, atomically */
 void pipe_wait(struct pipe_inode_info *pipe);
index f118809c953ff137b2a97e0d9e674b2836ee331a..747fcaedddb70d6cb0a49b43c0d2f2a6f23a693f 100644 (file)
@@ -139,7 +139,7 @@ extern int nr_processes(void);
 extern unsigned long nr_running(void);
 extern unsigned long nr_uninterruptible(void);
 extern unsigned long nr_iowait(void);
-extern unsigned long nr_iowait_cpu(void);
+extern unsigned long nr_iowait_cpu(int cpu);
 extern unsigned long this_cpu_load(void);
 
 
index f5364a1de68b105dac76e0125e93e767c21c2836..baed2122c5a608b209cf68f398cf6875ca2f6224 100644 (file)
@@ -2,9 +2,7 @@
 #define __LINUX_SERIAL_SCI_H
 
 #include <linux/serial_core.h>
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
-#include <asm/dmaengine.h>
-#endif
+#include <linux/sh_dma.h>
 
 /*
  * Generic header for SuperH SCI(F) (used by sh/sh64/h8300 and related parts)
index 7cdfb4d52847e6f733df1538f48fc73508e3d13e..f89e7fd59a4c4029a5e301b30c14df0ee7ae2699 100644 (file)
@@ -380,7 +380,10 @@ struct sk_buff {
        kmemcheck_bitfield_begin(flags2);
        __u16                   queue_mapping:16;
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
-       __u8                    ndisc_nodetype:2;
+       __u8                    ndisc_nodetype:2,
+                               deliver_no_wcard:1;
+#else
+       __u8                    deliver_no_wcard:1;
 #endif
        kmemcheck_bitfield_end(flags2);
 
@@ -501,7 +504,7 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
        return __alloc_skb(size, priority, 1, -1);
 }
 
-extern int skb_recycle_check(struct sk_buff *skb, int skb_size);
+extern bool skb_recycle_check(struct sk_buff *skb, int skb_size);
 
 extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
 extern struct sk_buff *skb_clone(struct sk_buff *skb,
index 89fac6a3f78b5feb7a832816fc7665cb639ce83d..f8854655860e3a10f5d708b9b749c43ead2bd48d 100644 (file)
@@ -60,7 +60,7 @@
 /*
  * Must define these before including other files, inline functions need them
  */
-#define LOCK_SECTION_NAME ".text.lock."KBUILD_BASENAME
+#define LOCK_SECTION_NAME ".text..lock."KBUILD_BASENAME
 
 #define LOCK_SECTION_START(extra)               \
         ".subsection 1\n\t"                     \
index 5e781d824e6d1680466479bdd6d726195203c55a..bc7d6bb4cd8ed261c4d7fe9acc2c91a2fa20e543 100644 (file)
@@ -256,22 +256,22 @@ static inline int hibernate(void) { return -ENOSYS; }
 static inline bool system_entering_hibernation(void) { return false; }
 #endif /* CONFIG_HIBERNATION */
 
-#ifdef CONFIG_HIBERNATION_NVS
-extern int hibernate_nvs_register(unsigned long start, unsigned long size);
-extern int hibernate_nvs_alloc(void);
-extern void hibernate_nvs_free(void);
-extern void hibernate_nvs_save(void);
-extern void hibernate_nvs_restore(void);
-#else /* CONFIG_HIBERNATION_NVS */
-static inline int hibernate_nvs_register(unsigned long a, unsigned long b)
+#ifdef CONFIG_SUSPEND_NVS
+extern int suspend_nvs_register(unsigned long start, unsigned long size);
+extern int suspend_nvs_alloc(void);
+extern void suspend_nvs_free(void);
+extern void suspend_nvs_save(void);
+extern void suspend_nvs_restore(void);
+#else /* CONFIG_SUSPEND_NVS */
+static inline int suspend_nvs_register(unsigned long a, unsigned long b)
 {
        return 0;
 }
-static inline int hibernate_nvs_alloc(void) { return 0; }
-static inline void hibernate_nvs_free(void) {}
-static inline void hibernate_nvs_save(void) {}
-static inline void hibernate_nvs_restore(void) {}
-#endif /* CONFIG_HIBERNATION_NVS */
+static inline int suspend_nvs_alloc(void) { return 0; }
+static inline void suspend_nvs_free(void) {}
+static inline void suspend_nvs_save(void) {}
+static inline void suspend_nvs_restore(void) {}
+#endif /* CONFIG_SUSPEND_NVS */
 
 #ifdef CONFIG_PM_SLEEP
 void save_processor_state(void);
index a1a86a53bc735c13cdda531309aa6c8158231909..7f614ce274a9198e969d573834d8782f95b8e6a3 100644 (file)
@@ -289,7 +289,7 @@ asmlinkage long sys_capget(cap_user_header_t header,
                                cap_user_data_t dataptr);
 asmlinkage long sys_capset(cap_user_header_t header,
                                const cap_user_data_t data);
-asmlinkage long sys_personality(u_long personality);
+asmlinkage long sys_personality(unsigned int personality);
 
 asmlinkage long sys_sigpending(old_sigset_t __user *set);
 asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set,
index 92f1d99f0f172c377dee4a33a7c6587d7e562bba..383b94ba8c2002f4f07e73eedbf8adb92a6211e1 100644 (file)
 /* v1.0 and v2.0 of this standard have many things in common. For the rest
  * of the definitions, please refer to audio.h */
 
+static inline bool uac2_control_is_readable(u32 bmControls, u8 control)
+{
+       return (bmControls >> (control * 2)) & 0x1;
+}
+
+static inline bool uac2_control_is_writeable(u32 bmControls, u8 control)
+{
+       return (bmControls >> (control * 2)) & 0x2;
+}
+
 /* 4.7.2.1 Clock Source Descriptor */
 
 struct uac_clock_source_descriptor {
@@ -31,6 +41,13 @@ struct uac_clock_source_descriptor {
        __u8 iClockSource;
 } __attribute__((packed));
 
+/* bmAttribute fields */
+#define UAC_CLOCK_SOURCE_TYPE_EXT      0x0
+#define UAC_CLOCK_SOURCE_TYPE_INT_FIXED        0x1
+#define UAC_CLOCK_SOURCE_TYPE_INT_VAR  0x2
+#define UAC_CLOCK_SOURCE_TYPE_INT_PROG 0x3
+#define UAC_CLOCK_SOURCE_SYNCED_TO_SOF (1 << 2)
+
 /* 4.7.2.2 Clock Source Descriptor */
 
 struct uac_clock_selector_descriptor {
@@ -39,8 +56,20 @@ struct uac_clock_selector_descriptor {
        __u8 bDescriptorSubtype;
        __u8 bClockID;
        __u8 bNrInPins;
-       __u8 bmControls;
        __u8 baCSourceID[];
+       /* bmControls, bAssocTerminal and iClockSource omitted */
+} __attribute__((packed));
+
+/* 4.7.2.3 Clock Multiplier Descriptor */
+
+struct uac_clock_multiplier_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bClockID;
+       __u8 bCSourceID;
+       __u8 bmControls;
+       __u8 iClockMultiplier;
 } __attribute__((packed));
 
 /* 4.7.2.4 Input terminal descriptor */
index 5d646c3887524febf0d39f81d2e7c4a832f875fe..c51200c715e504a951a5b18a74a599abbede08a1 100644 (file)
 #define UAC_FORMAT_TYPE                        0x02
 #define UAC_FORMAT_SPECIFIC            0x03
 
+/* A.7 Processing Unit Process Types */
+#define UAC_PROCESS_UNDEFINED          0x00
+#define UAC_PROCESS_UP_DOWNMIX         0x01
+#define UAC_PROCESS_DOLBY_PROLOGIC     0x02
+#define UAC_PROCESS_STEREO_EXTENDER    0x03
+#define UAC_PROCESS_REVERB             0x04
+#define UAC_PROCESS_CHORUS             0x05
+#define UAC_PROCESS_DYN_RANGE_COMP     0x06
+
 /* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */
 #define UAC_EP_GENERAL                 0x01
 
 
 #define UAC_GET_STAT                   0xff
 
+/* A.10 Control Selector Codes */
+
+/* A.10.1 Terminal Control Selectors */
+#define UAC_TERM_COPY_PROTECT          0x01
+
+/* A.10.2 Feature Unit Control Selectors */
+#define UAC_FU_MUTE                    0x01
+#define UAC_FU_VOLUME                  0x02
+#define UAC_FU_BASS                    0x03
+#define UAC_FU_MID                     0x04
+#define UAC_FU_TREBLE                  0x05
+#define UAC_FU_GRAPHIC_EQUALIZER       0x06
+#define UAC_FU_AUTOMATIC_GAIN          0x07
+#define UAC_FU_DELAY                   0x08
+#define UAC_FU_BASS_BOOST              0x09
+#define UAC_FU_LOUDNESS                        0x0a
+
+#define UAC_CONTROL_BIT(CS)    (1 << ((CS) - 1))
+
+/* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */
+#define UAC_UD_ENABLE                  0x01
+#define UAC_UD_MODE_SELECT             0x02
+
+/* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */
+#define UAC_DP_ENABLE                  0x01
+#define UAC_DP_MODE_SELECT             0x02
+
+/* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */
+#define UAC_3D_ENABLE                  0x01
+#define UAC_3D_SPACE                   0x02
+
+/* A.10.3.4 Reverberation Processing Unit Control Selectors */
+#define UAC_REVERB_ENABLE              0x01
+#define UAC_REVERB_LEVEL               0x02
+#define UAC_REVERB_TIME                        0x03
+#define UAC_REVERB_FEEDBACK            0x04
+
+/* A.10.3.5 Chorus Processing Unit Control Selectors */
+#define UAC_CHORUS_ENABLE              0x01
+#define UAC_CHORUS_LEVEL               0x02
+#define UAC_CHORUS_RATE                        0x03
+#define UAC_CHORUS_DEPTH               0x04
+
+/* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */
+#define UAC_DCR_ENABLE                 0x01
+#define UAC_DCR_RATE                   0x02
+#define UAC_DCR_MAXAMPL                        0x03
+#define UAC_DCR_THRESHOLD              0x04
+#define UAC_DCR_ATTACK_TIME            0x05
+#define UAC_DCR_RELEASE_TIME           0x06
+
+/* A.10.4 Extension Unit Control Selectors */
+#define UAC_XU_ENABLE                  0x01
+
 /* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */
 #define UAC_MS_HEADER                  0x01
 #define UAC_MIDI_IN_JACK               0x02
@@ -244,7 +307,7 @@ struct uac_selector_unit_descriptor {
 static inline __u8 uac_selector_unit_iSelector(struct uac_selector_unit_descriptor *desc)
 {
        __u8 *raw = (__u8 *) desc;
-       return raw[9 + desc->bLength - 1];
+       return raw[desc->bLength - 1];
 }
 
 /* 4.3.2.5 Feature Unit Descriptor */
@@ -463,31 +526,6 @@ struct uac_iso_endpoint_descriptor {
 #define UAC_EP_CS_ATTR_PITCH_CONTROL   0x02
 #define UAC_EP_CS_ATTR_FILL_MAX                0x80
 
-/* A.10.2 Feature Unit Control Selectors */
-
-#define UAC_FU_CONTROL_UNDEFINED       0x00
-#define UAC_MUTE_CONTROL               0x01
-#define UAC_VOLUME_CONTROL             0x02
-#define UAC_BASS_CONTROL               0x03
-#define UAC_MID_CONTROL                        0x04
-#define UAC_TREBLE_CONTROL             0x05
-#define UAC_GRAPHIC_EQUALIZER_CONTROL  0x06
-#define UAC_AUTOMATIC_GAIN_CONTROL     0x07
-#define UAC_DELAY_CONTROL              0x08
-#define UAC_BASS_BOOST_CONTROL         0x09
-#define UAC_LOUDNESS_CONTROL           0x0a
-
-#define UAC_FU_MUTE            (1 << (UAC_MUTE_CONTROL - 1))
-#define UAC_FU_VOLUME          (1 << (UAC_VOLUME_CONTROL - 1))
-#define UAC_FU_BASS            (1 << (UAC_BASS_CONTROL - 1))
-#define UAC_FU_MID             (1 << (UAC_MID_CONTROL - 1))
-#define UAC_FU_TREBLE          (1 << (UAC_TREBLE_CONTROL - 1))
-#define UAC_FU_GRAPHIC_EQ      (1 << (UAC_GRAPHIC_EQUALIZER_CONTROL - 1))
-#define UAC_FU_AUTO_GAIN       (1 << (UAC_AUTOMATIC_GAIN_CONTROL - 1))
-#define UAC_FU_DELAY           (1 << (UAC_DELAY_CONTROL - 1))
-#define UAC_FU_BASS_BOOST      (1 << (UAC_BASS_BOOST_CONTROL - 1))
-#define UAC_FU_LOUDNESS                (1 << (UAC_LOUDNESS_CONTROL - 1))
-
 /* status word format (3.7.1.1) */
 
 #define UAC1_STATUS_TYPE_ORIG_MASK             0x0f
index 2dfaa293ae8c971303092235da547b5afb438319..c9a97597699522db33b2f309bd58368970eb9651 100644 (file)
@@ -5,6 +5,27 @@
  * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
  * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
  * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS
+ * IN THE SOFTWARE.
+ *
  */
 
 #ifndef LINUX_VGA_H
index cc97d6caf2b32af24505ebbc73d7f98265efbde1..d63ef8f9609fde16ee9bbbcfea4d9c30818c0dd6 100644 (file)
@@ -56,24 +56,6 @@ struct writeback_control {
        unsigned for_reclaim:1;         /* Invoked from the page allocator */
        unsigned range_cyclic:1;        /* range_start is cyclic */
        unsigned more_io:1;             /* more io to be dispatched */
-       /*
-        * write_cache_pages() won't update wbc->nr_to_write and
-        * mapping->writeback_index if no_nrwrite_index_update
-        * is set.  write_cache_pages() may write more than we
-        * requested and we want to make sure nr_to_write and
-        * writeback_index are updated in a consistent manner
-        * so we use a single control to update them
-        */
-       unsigned no_nrwrite_index_update:1;
-
-       /*
-        * For WB_SYNC_ALL, the sb must always be pinned. For WB_SYNC_NONE,
-        * the writeback code will pin the sb for the caller. However,
-        * for eg umount, the caller does WB_SYNC_NONE but already has
-        * the sb pinned. If the below is set, caller already has the
-        * sb pinned.
-        */
-       unsigned sb_pinned:1;
 };
 
 /*
@@ -82,7 +64,6 @@ struct writeback_control {
 struct bdi_writeback;
 int inode_wait(void *);
 void writeback_inodes_sb(struct super_block *);
-void writeback_inodes_sb_locked(struct super_block *);
 int writeback_inodes_sb_if_idle(struct super_block *);
 void sync_inodes_sb(struct super_block *);
 void writeback_inodes_wbc(struct writeback_control *wbc);
index 5833966a710036ce02f9ca88f81502154b3446bd..c78e99a435b6c019438059e84d72a67e55fc2bd8 100644 (file)
@@ -55,7 +55,8 @@ void rc_map_init(void);
 #define RC_MAP_AVERMEDIA_A16D            "rc-avermedia-a16d"
 #define RC_MAP_AVERMEDIA_CARDBUS         "rc-avermedia-cardbus"
 #define RC_MAP_AVERMEDIA_DVBT            "rc-avermedia-dvbt"
-#define RC_MAP_AVERMEDIA_M135A_RM_JX     "rc-avermedia-m135a-rm-jx"
+#define RC_MAP_AVERMEDIA_M135A           "rc-avermedia-m135a"
+#define RC_MAP_AVERMEDIA_M733A_RM_K6     "rc-avermedia-m733a-rm-k6"
 #define RC_MAP_AVERMEDIA                 "rc-avermedia"
 #define RC_MAP_AVERTV_303                "rc-avertv-303"
 #define RC_MAP_BEHOLD_COLUMBUS           "rc-behold-columbus"
index c9a5bbfa6ab5f91cdab0e90e548fea322bd47f0a..b8289c2f609b431cf6da04388bdfd679a2db65c8 100644 (file)
@@ -66,7 +66,7 @@ struct soc_camera_host_ops {
         * .get_formats() fail, .put_formats() will not be called at all, the
         * failing .get_formats() must then clean up internally.
         */
-       int (*get_formats)(struct soc_camera_device *, int,
+       int (*get_formats)(struct soc_camera_device *, unsigned int,
                           struct soc_camera_format_xlate *);
        void (*put_formats)(struct soc_camera_device *);
        int (*cropcap)(struct soc_camera_device *, struct v4l2_cropcap *);
index 0dbe02ada259cecc22e8625f2deed8aef03fb793..865cda7cd611d729f634a231ee6ba54194dd0101 100644 (file)
@@ -40,6 +40,7 @@ enum v4l2_mbus_pixelcode {
        V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
        V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
        V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
+       V4L2_MBUS_FMT_SGRBG8_1X8,
 };
 
 /**
@@ -58,4 +59,24 @@ struct v4l2_mbus_framefmt {
        enum v4l2_colorspace            colorspace;
 };
 
+static inline void v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt,
+                               const struct v4l2_mbus_framefmt *mbus_fmt)
+{
+       pix_fmt->width = mbus_fmt->width;
+       pix_fmt->height = mbus_fmt->height;
+       pix_fmt->field = mbus_fmt->field;
+       pix_fmt->colorspace = mbus_fmt->colorspace;
+}
+
+static inline void v4l2_fill_mbus_format(struct v4l2_mbus_framefmt *mbus_fmt,
+                          const struct v4l2_pix_format *pix_fmt,
+                          enum v4l2_mbus_pixelcode code)
+{
+       mbus_fmt->width = pix_fmt->width;
+       mbus_fmt->height = pix_fmt->height;
+       mbus_fmt->field = pix_fmt->field;
+       mbus_fmt->colorspace = pix_fmt->colorspace;
+       mbus_fmt->code = code;
+}
+
 #endif
index a88889355ae0a4bb6edb6e4fc05893eab551d029..02c6f4d11ed3654d76e2908983b26353361d2b1a 100644 (file)
@@ -246,7 +246,7 @@ struct v4l2_subdev_video_ops {
                        struct v4l2_dv_timings *timings);
        int (*g_dv_timings)(struct v4l2_subdev *sd,
                        struct v4l2_dv_timings *timings);
-       int (*enum_mbus_fmt)(struct v4l2_subdev *sd, int index,
+       int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index,
                             enum v4l2_mbus_pixelcode *code);
        int (*g_mbus_fmt)(struct v4l2_subdev *sd,
                          struct v4l2_mbus_framefmt *fmt);
index 612069beda733676b1e106ce8f24ee19e66b8910..81d1413a87010967684febe7344169baa7d828ef 100644 (file)
@@ -250,11 +250,11 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
  * Linux networking.  Thus, destinations are stackable.
  */
 
-static inline struct dst_entry *dst_pop(struct dst_entry *dst)
+static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
 {
-       struct dst_entry *child = dst_clone(dst->child);
+       struct dst_entry *child = skb_dst(skb)->child;
 
-       dst_release(dst);
+       skb_dst_drop(skb);
        return child;
 }
 
index 92456f1035f52bd6e1a6c8e7733c7737d58d15e1..899003d18db9e57ab8813176f4ea896a27376c49 100644 (file)
@@ -134,7 +134,7 @@ struct linux_xfrm_mib {
 #define SNMP_ADD_STATS_USER(mib, field, addend)        \
                        this_cpu_add(mib[1]->mibs[field], addend)
 #define SNMP_ADD_STATS(mib, field, addend)     \
-                       this_cpu_add(mib[0]->mibs[field], addend)
+                       this_cpu_add(mib[!in_softirq()]->mibs[field], addend)
 /*
  * Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr"
  * to make @ptr a non-percpu pointer.
index ca241ea148758a555d123343e2fe8639f7dd5bd3..731150d52799ecc5492b3590c3b7b5b34de09072 100644 (file)
@@ -1524,20 +1524,7 @@ extern void sk_stop_timer(struct sock *sk, struct timer_list* timer);
 
 extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 
-static inline int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
-{
-       /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
-          number of warnings when compiling with -W --ANK
-        */
-       if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
-           (unsigned)sk->sk_rcvbuf)
-               return -ENOMEM;
-       skb_set_owner_r(skb, sk);
-       skb_queue_tail(&sk->sk_error_queue, skb);
-       if (!sock_flag(sk, SOCK_DEAD))
-               sk->sk_data_ready(sk, skb->len);
-       return 0;
-}
+extern int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb);
 
 /*
  *     Recover an error report and clear atomically
index c50a97fc76f9418ec1ce7ceddd4b8e140e9831ea..b7bdecb7b76efe6b11efe43063798c9887707f8b 100644 (file)
@@ -326,6 +326,14 @@ struct scsi_host_template {
        int (* bios_param)(struct scsi_device *, struct block_device *,
                        sector_t, int []);
 
+       /*
+        * This function is called when one or more partitions on the
+        * device reach beyond the end of the device.
+        *
+        * Status: OPTIONAL
+        */
+       void (*unlock_native_capacity)(struct scsi_device *);
+
        /*
         * Can be used to export driver statistics and other infos to the
         * world outside the kernel ie. userspace and it also provides an
index f5b1ba90e952f71535d13b8c0a7d9a68782d5a07..f3865c7b4166e315da77d9c342b977b9d4338915 100644 (file)
@@ -306,7 +306,6 @@ TRACE_EVENT(ext4_da_writepages_result,
                __field(        int,    pages_written           )
                __field(        long,   pages_skipped           )
                __field(        char,   more_io                 )       
-               __field(        char,   no_nrwrite_index_update )
                __field(       pgoff_t, writeback_index         )
        ),
 
@@ -317,16 +316,14 @@ TRACE_EVENT(ext4_da_writepages_result,
                __entry->pages_written  = pages_written;
                __entry->pages_skipped  = wbc->pages_skipped;
                __entry->more_io        = wbc->more_io;
-               __entry->no_nrwrite_index_update = wbc->no_nrwrite_index_update;
                __entry->writeback_index = inode->i_mapping->writeback_index;
        ),
 
-       TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld more_io %d no_nrwrite_index_update %d writeback_index %lu",
+       TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld more_io %d writeback_index %lu",
                  jbd2_dev_to_name(__entry->dev),
                  (unsigned long) __entry->ino, __entry->ret,
                  __entry->pages_written, __entry->pages_skipped,
                  __entry->more_io,
-                 __entry->no_nrwrite_index_update,
                  (unsigned long) __entry->writeback_index)
 );
 
index 4f733ecea46e8cd464d05c92d5610f57c10a59fc..b9e1dd6c6208b62b9201b7b9bff947fcfb0f2c51 100644 (file)
@@ -115,6 +115,23 @@ DEFINE_EVENT(sched_wakeup_template, sched_wakeup_new,
             TP_PROTO(struct task_struct *p, int success),
             TP_ARGS(p, success));
 
+#ifdef CREATE_TRACE_POINTS
+static inline long __trace_sched_switch_state(struct task_struct *p)
+{
+       long state = p->state;
+
+#ifdef CONFIG_PREEMPT
+       /*
+        * For all intents and purposes a preempted task is a running task.
+        */
+       if (task_thread_info(p)->preempt_count & PREEMPT_ACTIVE)
+               state = TASK_RUNNING;
+#endif
+
+       return state;
+}
+#endif
+
 /*
  * Tracepoint for task switches, performed by the scheduler:
  */
@@ -139,7 +156,7 @@ TRACE_EVENT(sched_switch,
                memcpy(__entry->next_comm, next->comm, TASK_COMM_LEN);
                __entry->prev_pid       = prev->pid;
                __entry->prev_prio      = prev->prio;
-               __entry->prev_state     = prev->state;
+               __entry->prev_state     = __trace_sched_switch_state(prev);
                memcpy(__entry->prev_comm, prev->comm, TASK_COMM_LEN);
                __entry->next_pid       = next->pid;
                __entry->next_prio      = next->prio;
index 2cce9f343ad0b6397ba7ce2103a3d8c88eaedd0c..5cff9a980c397d48491145e9d1f9e4e42313cad4 100644 (file)
@@ -76,6 +76,14 @@ config INIT_ENV_ARG_LIMIT
          variables passed to init from the kernel command line.
 
 
+config CROSS_COMPILE
+       string "Cross-compiler tool prefix"
+       help
+         Same as running 'make CROSS_COMPILE=prefix-' but stored for
+         default make runs in this kernel build directory.  You don't
+         need to set this unless you want the configured kernel build
+         directory to select the cross-compiler automatically.
+
 config LOCALVERSION
        string "Local version - append to kernel release"
        help
index 3bdb152f412f32b8edeeb1036a24f934988b5be2..a42fdf4aeba91ada21882d86d552ed722c00eb5a 100644 (file)
@@ -125,7 +125,9 @@ static char *ramdisk_execute_command;
 
 #ifdef CONFIG_SMP
 /* Setup configured maximum number of CPUs to activate */
-unsigned int __initdata setup_max_cpus = NR_CPUS;
+unsigned int setup_max_cpus = NR_CPUS;
+EXPORT_SYMBOL(setup_max_cpus);
+
 
 /*
  * Setup routine for controlling SMP activation
@@ -422,18 +424,26 @@ static void __init setup_command_line(char *command_line)
  * gcc-3.4 accidentally inlines this function, so use noinline.
  */
 
+static __initdata DECLARE_COMPLETION(kthreadd_done);
+
 static noinline void __init_refok rest_init(void)
        __releases(kernel_lock)
 {
        int pid;
 
        rcu_scheduler_starting();
+       /*
+        * We need to spawn init first so that it obtains pid 1, however
+        * the init task will end up wanting to create kthreads, which, if
+        * we schedule it before we create kthreadd, will OOPS.
+        */
        kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
        numa_default_policy();
        pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
        rcu_read_lock();
        kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
        rcu_read_unlock();
+       complete(&kthreadd_done);
        unlock_kernel();
 
        /*
@@ -855,6 +865,10 @@ static noinline int init_post(void)
 
 static int __init kernel_init(void * unused)
 {
+       /*
+        * Wait until kthreadd is all set-up.
+        */
+       wait_for_completion(&kthreadd_done);
        lock_kernel();
 
        /*
index 5108232f93d48ec008f0418737238c50e810ba15..c93fd3faac2d288e7d87db2642df7b167e15ddc0 100644 (file)
@@ -176,7 +176,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
        }
        return inode;
 out_inode:
-       make_bad_inode(inode);
        iput(inode);
        return NULL;
 }
index 422cb19f156ef9b7a6f5ab8968ade8a618ea5d88..3ac6f5b0a64b7448aceac7407c04cf7109f7ef5d 100644 (file)
@@ -4598,7 +4598,7 @@ static int alloc_css_id(struct cgroup_subsys *ss, struct cgroup *parent,
        parent_css = parent->subsys[subsys_id];
        child_css = child->subsys[subsys_id];
        parent_id = parent_css->id;
-       depth = parent_id->depth;
+       depth = parent_id->depth + 1;
 
        child_id = get_new_cssid(ss, depth);
        if (IS_ERR(child_id))
index 8b92539b4754274528fdc380d45baf6d481001b1..97d1b426a4ac39bd49b41b9393ed9b565f8f7f33 100644 (file)
@@ -34,7 +34,7 @@ void cpu_maps_update_done(void)
        mutex_unlock(&cpu_add_remove_lock);
 }
 
-static __cpuinitdata RAW_NOTIFIER_HEAD(cpu_chain);
+static RAW_NOTIFIER_HEAD(cpu_chain);
 
 /* If set, cpu_up and cpu_down will return -EBUSY and do nothing.
  * Should always be manipulated under cpu_add_remove_lock
index b724c791b6d45d7bf39a32ca0b9d02881055de9d..184cd8209c365de082c70c354f25758d22339ed8 100644 (file)
@@ -1857,12 +1857,6 @@ static int kdb_ef(int argc, const char **argv)
 }
 
 #if defined(CONFIG_MODULES)
-/* modules using other modules */
-struct module_use {
-       struct list_head list;
-       struct module *module_which_uses;
-};
-
 /*
  * kdb_lsmod - This function implements the 'lsmod' command.  Lists
  *     currently loaded kernel modules.
@@ -1894,9 +1888,9 @@ static int kdb_lsmod(int argc, const char **argv)
                {
                        struct module_use *use;
                        kdb_printf(" [ ");
-                       list_for_each_entry(use, &mod->modules_which_use_me,
-                                           list)
-                               kdb_printf("%s ", use->module_which_uses->name);
+                       list_for_each_entry(use, &mod->source_list,
+                                           source_list)
+                               kdb_printf("%s ", use->target->name);
                        kdb_printf("]\n");
                }
 #endif
index c35452cadded85de8e4505def877b3c5561c991f..dd62f8e714ca52d2fed7a7b14b03a6ee9a53d2f1 100644 (file)
@@ -27,7 +27,7 @@ static struct exec_domain *exec_domains = &default_exec_domain;
 static DEFINE_RWLOCK(exec_domains_lock);
 
 
-static u_long ident_map[32] = {
+static unsigned long ident_map[32] = {
        0,      1,      2,      3,      4,      5,      6,      7,
        8,      9,      10,     11,     12,     13,     14,     15,
        16,     17,     18,     19,     20,     21,     22,     23,
@@ -56,10 +56,10 @@ default_handler(int segment, struct pt_regs *regp)
 }
 
 static struct exec_domain *
-lookup_exec_domain(u_long personality)
+lookup_exec_domain(unsigned int personality)
 {
-       struct exec_domain *    ep;
-       u_long                  pers = personality(personality);
+       unsigned int pers = personality(personality);
+       struct exec_domain *ep;
 
        read_lock(&exec_domains_lock);
        for (ep = exec_domains; ep; ep = ep->next) {
@@ -70,7 +70,7 @@ lookup_exec_domain(u_long personality)
 
 #ifdef CONFIG_MODULES
        read_unlock(&exec_domains_lock);
-       request_module("personality-%ld", pers);
+       request_module("personality-%d", pers);
        read_lock(&exec_domains_lock);
 
        for (ep = exec_domains; ep; ep = ep->next) {
@@ -135,7 +135,7 @@ unregister:
 }
 
 int
-__set_personality(u_long personality)
+__set_personality(unsigned int personality)
 {
        struct exec_domain      *ep, *oep;
 
@@ -188,9 +188,9 @@ static int __init proc_execdomains_init(void)
 module_init(proc_execdomains_init);
 #endif
 
-SYSCALL_DEFINE1(personality, u_long, personality)
+SYSCALL_DEFINE1(personality, unsigned int, personality)
 {
-       u_long old = current->personality;
+       unsigned int old = current->personality;
 
        if (personality != 0xffffffff) {
                set_personality(personality);
@@ -198,7 +198,7 @@ SYSCALL_DEFINE1(personality, u_long, personality)
                        return -EINVAL;
        }
 
-       return (long)old;
+       return old;
 }
 
 
index e7a35f1039e785464b318d3713557e9d2db6a591..6a3a5fa1526d87d16b362e20d7d62e6809285c18 100644 (file)
@@ -429,20 +429,11 @@ static void free_pi_state(struct futex_pi_state *pi_state)
 static struct task_struct * futex_find_get_task(pid_t pid)
 {
        struct task_struct *p;
-       const struct cred *cred = current_cred(), *pcred;
 
        rcu_read_lock();
        p = find_task_by_vpid(pid);
-       if (!p) {
-               p = ERR_PTR(-ESRCH);
-       } else {
-               pcred = __task_cred(p);
-               if (cred->euid != pcred->euid &&
-                   cred->euid != pcred->uid)
-                       p = ERR_PTR(-ESRCH);
-               else
-                       get_task_struct(p);
-       }
+       if (p)
+               get_task_struct(p);
 
        rcu_read_unlock();
 
@@ -564,8 +555,8 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
        if (!pid)
                return -ESRCH;
        p = futex_find_get_task(pid);
-       if (IS_ERR(p))
-               return PTR_ERR(p);
+       if (!p)
+               return -ESRCH;
 
        /*
         * We need to look at the task state flags to figure out,
index 3164ba7ce151cf6c228613ddce2195450af30012..e1497481fe8a6feab3554173fb313ebbef59bb39 100644 (file)
@@ -456,6 +456,9 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
                /* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
                desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK);
                desc->status |= flags;
+
+               if (chip != desc->chip)
+                       irq_chip_set_defaults(desc->chip);
        }
 
        return ret;
index 474a84715eaca2936b51ad5a6c46fb4774751c5b..131b1703936f6dbe71cf84c2ff572efef6c47e70 100644 (file)
@@ -1089,9 +1089,10 @@ void crash_kexec(struct pt_regs *regs)
 
 size_t crash_get_memory_size(void)
 {
-       size_t size;
+       size_t size = 0;
        mutex_lock(&kexec_mutex);
-       size = crashk_res.end - crashk_res.start + 1;
+       if (crashk_res.end != crashk_res.start)
+               size = crashk_res.end - crashk_res.start + 1;
        mutex_unlock(&kexec_mutex);
        return size;
 }
@@ -1134,7 +1135,7 @@ int crash_shrink_memory(unsigned long new_size)
 
        free_reserved_phys_range(end, crashk_res.end);
 
-       if (start == end)
+       if ((start == end) && (crashk_res.parent != NULL))
                release_resource(&crashk_res);
        crashk_res.end = end - 1;
 
index 333fbcc969783a7cca1728f141c870be7b24e918..5d2d28197c827a840d98357c11c1e16b3dce92a2 100644 (file)
 /* If this is set, the section belongs in the init part of the module */
 #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
 
-/* List of modules, protected by module_mutex or preempt_disable
+/*
+ * Mutex protects:
+ * 1) List of modules (also safely readable with preempt_disable),
+ * 2) module_use links,
+ * 3) module_addr_min/module_addr_max.
  * (delete uses stop_machine/add uses RCU list operations). */
 DEFINE_MUTEX(module_mutex);
 EXPORT_SYMBOL_GPL(module_mutex);
@@ -90,7 +94,8 @@ static DECLARE_WAIT_QUEUE_HEAD(module_wq);
 
 static BLOCKING_NOTIFIER_HEAD(module_notify_list);
 
-/* Bounds of module allocation, for speeding __module_address */
+/* Bounds of module allocation, for speeding __module_address.
+ * Protected by module_mutex. */
 static unsigned long module_addr_min = -1UL, module_addr_max = 0;
 
 int register_module_notifier(struct notifier_block * nb)
@@ -329,7 +334,7 @@ static bool find_symbol_in_section(const struct symsearch *syms,
 }
 
 /* Find a symbol and return it, along with, (optional) crc and
- * (optional) module which owns it */
+ * (optional) module which owns it.  Needs preempt disabled or module_mutex. */
 const struct kernel_symbol *find_symbol(const char *name,
                                        struct module **owner,
                                        const unsigned long **crc,
@@ -403,7 +408,7 @@ static unsigned int find_pcpusec(Elf_Ehdr *hdr,
                                 Elf_Shdr *sechdrs,
                                 const char *secstrings)
 {
-       return find_sec(hdr, sechdrs, secstrings, ".data.percpu");
+       return find_sec(hdr, sechdrs, secstrings, ".data..percpu");
 }
 
 static void percpu_modcopy(struct module *mod,
@@ -523,7 +528,8 @@ static void module_unload_init(struct module *mod)
 {
        int cpu;
 
-       INIT_LIST_HEAD(&mod->modules_which_use_me);
+       INIT_LIST_HEAD(&mod->source_list);
+       INIT_LIST_HEAD(&mod->target_list);
        for_each_possible_cpu(cpu) {
                per_cpu_ptr(mod->refptr, cpu)->incs = 0;
                per_cpu_ptr(mod->refptr, cpu)->decs = 0;
@@ -535,20 +541,13 @@ static void module_unload_init(struct module *mod)
        mod->waiter = current;
 }
 
-/* modules using other modules */
-struct module_use
-{
-       struct list_head list;
-       struct module *module_which_uses;
-};
-
 /* Does a already use b? */
 static int already_uses(struct module *a, struct module *b)
 {
        struct module_use *use;
 
-       list_for_each_entry(use, &b->modules_which_use_me, list) {
-               if (use->module_which_uses == a) {
+       list_for_each_entry(use, &b->source_list, source_list) {
+               if (use->source == a) {
                        DEBUGP("%s uses %s!\n", a->name, b->name);
                        return 1;
                }
@@ -557,62 +556,68 @@ static int already_uses(struct module *a, struct module *b)
        return 0;
 }
 
-/* Module a uses b */
-int use_module(struct module *a, struct module *b)
+/*
+ * Module a uses b
+ *  - we add 'a' as a "source", 'b' as a "target" of module use
+ *  - the module_use is added to the list of 'b' sources (so
+ *    'b' can walk the list to see who sourced them), and of 'a'
+ *    targets (so 'a' can see what modules it targets).
+ */
+static int add_module_usage(struct module *a, struct module *b)
 {
        struct module_use *use;
-       int no_warn, err;
 
-       if (b == NULL || already_uses(a, b)) return 1;
+       DEBUGP("Allocating new usage for %s.\n", a->name);
+       use = kmalloc(sizeof(*use), GFP_ATOMIC);
+       if (!use) {
+               printk(KERN_WARNING "%s: out of memory loading\n", a->name);
+               return -ENOMEM;
+       }
+
+       use->source = a;
+       use->target = b;
+       list_add(&use->source_list, &b->source_list);
+       list_add(&use->target_list, &a->target_list);
+       return 0;
+}
 
-       /* If we're interrupted or time out, we fail. */
-       if (wait_event_interruptible_timeout(
-                   module_wq, (err = strong_try_module_get(b)) != -EBUSY,
-                   30 * HZ) <= 0) {
-               printk("%s: gave up waiting for init of module %s.\n",
-                      a->name, b->name);
+/* Module a uses b: caller needs module_mutex() */
+int ref_module(struct module *a, struct module *b)
+{
+       int err;
+
+       if (b == NULL || already_uses(a, b))
                return 0;
-       }
 
-       /* If strong_try_module_get() returned a different error, we fail. */
+       /* If module isn't available, we fail. */
+       err = strong_try_module_get(b);
        if (err)
-               return 0;
+               return err;
 
-       DEBUGP("Allocating new usage for %s.\n", a->name);
-       use = kmalloc(sizeof(*use), GFP_ATOMIC);
-       if (!use) {
-               printk("%s: out of memory loading\n", a->name);
+       err = add_module_usage(a, b);
+       if (err) {
                module_put(b);
-               return 0;
+               return err;
        }
-
-       use->module_which_uses = a;
-       list_add(&use->list, &b->modules_which_use_me);
-       no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name);
-       return 1;
+       return 0;
 }
-EXPORT_SYMBOL_GPL(use_module);
+EXPORT_SYMBOL_GPL(ref_module);
 
 /* Clear the unload stuff of the module. */
 static void module_unload_free(struct module *mod)
 {
-       struct module *i;
-
-       list_for_each_entry(i, &modules, list) {
-               struct module_use *use;
+       struct module_use *use, *tmp;
 
-               list_for_each_entry(use, &i->modules_which_use_me, list) {
-                       if (use->module_which_uses == mod) {
-                               DEBUGP("%s unusing %s\n", mod->name, i->name);
-                               module_put(i);
-                               list_del(&use->list);
-                               kfree(use);
-                               sysfs_remove_link(i->holders_dir, mod->name);
-                               /* There can be at most one match. */
-                               break;
-                       }
-               }
+       mutex_lock(&module_mutex);
+       list_for_each_entry_safe(use, tmp, &mod->target_list, target_list) {
+               struct module *i = use->target;
+               DEBUGP("%s unusing %s\n", mod->name, i->name);
+               module_put(i);
+               list_del(&use->source_list);
+               list_del(&use->target_list);
+               kfree(use);
        }
+       mutex_unlock(&module_mutex);
 }
 
 #ifdef CONFIG_MODULE_FORCE_UNLOAD
@@ -735,7 +740,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
                goto out;
        }
 
-       if (!list_empty(&mod->modules_which_use_me)) {
+       if (!list_empty(&mod->source_list)) {
                /* Other modules depend on us: get rid of them first. */
                ret = -EWOULDBLOCK;
                goto out;
@@ -779,13 +784,14 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_GOING, mod);
        async_synchronize_full();
-       mutex_lock(&module_mutex);
+
        /* Store the name of the last unloaded module for diagnostic purposes */
        strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
        ddebug_remove_module(mod->name);
-       free_module(mod);
 
- out:
+       free_module(mod);
+       return 0;
+out:
        mutex_unlock(&module_mutex);
        return ret;
 }
@@ -799,9 +805,9 @@ static inline void print_unload_info(struct seq_file *m, struct module *mod)
 
        /* Always include a trailing , so userspace can differentiate
            between this and the old multi-field proc format. */
-       list_for_each_entry(use, &mod->modules_which_use_me, list) {
+       list_for_each_entry(use, &mod->source_list, source_list) {
                printed_something = 1;
-               seq_printf(m, "%s,", use->module_which_uses->name);
+               seq_printf(m, "%s,", use->source->name);
        }
 
        if (mod->init != NULL && mod->exit == NULL) {
@@ -880,11 +886,11 @@ static inline void module_unload_free(struct module *mod)
 {
 }
 
-int use_module(struct module *a, struct module *b)
+int ref_module(struct module *a, struct module *b)
 {
-       return strong_try_module_get(b) == 0;
+       return strong_try_module_get(b);
 }
-EXPORT_SYMBOL_GPL(use_module);
+EXPORT_SYMBOL_GPL(ref_module);
 
 static inline void module_unload_init(struct module *mod)
 {
@@ -1001,6 +1007,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
 {
        const unsigned long *crc;
 
+       /* Since this should be found in kernel (which can't be removed),
+        * no locking is necessary. */
        if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL,
                         &crc, true, false))
                BUG();
@@ -1043,29 +1051,62 @@ static inline int same_magic(const char *amagic, const char *bmagic,
 }
 #endif /* CONFIG_MODVERSIONS */
 
-/* Resolve a symbol for this module.  I.e. if we find one, record usage.
-   Must be holding module_mutex. */
+/* Resolve a symbol for this module.  I.e. if we find one, record usage. */
 static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs,
                                                  unsigned int versindex,
                                                  const char *name,
-                                                 struct module *mod)
+                                                 struct module *mod,
+                                                 char ownername[])
 {
        struct module *owner;
        const struct kernel_symbol *sym;
        const unsigned long *crc;
+       int err;
 
+       mutex_lock(&module_mutex);
        sym = find_symbol(name, &owner, &crc,
                          !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
-       /* use_module can fail due to OOM,
-          or module initialization or unloading */
-       if (sym) {
-               if (!check_version(sechdrs, versindex, name, mod, crc, owner)
-                   || !use_module(mod, owner))
-                       sym = NULL;
+       if (!sym)
+               goto unlock;
+
+       if (!check_version(sechdrs, versindex, name, mod, crc, owner)) {
+               sym = ERR_PTR(-EINVAL);
+               goto getname;
        }
+
+       err = ref_module(mod, owner);
+       if (err) {
+               sym = ERR_PTR(err);
+               goto getname;
+       }
+
+getname:
+       /* We must make copy under the lock if we failed to get ref. */
+       strncpy(ownername, module_name(owner), MODULE_NAME_LEN);
+unlock:
+       mutex_unlock(&module_mutex);
        return sym;
 }
 
+static const struct kernel_symbol *resolve_symbol_wait(Elf_Shdr *sechdrs,
+                                                      unsigned int versindex,
+                                                      const char *name,
+                                                      struct module *mod)
+{
+       const struct kernel_symbol *ksym;
+       char ownername[MODULE_NAME_LEN];
+
+       if (wait_event_interruptible_timeout(module_wq,
+                       !IS_ERR(ksym = resolve_symbol(sechdrs, versindex, name,
+                                                     mod, ownername)) ||
+                       PTR_ERR(ksym) != -EBUSY,
+                                            30 * HZ) <= 0) {
+               printk(KERN_WARNING "%s: gave up waiting for init of module %s.\n",
+                      mod->name, ownername);
+       }
+       return ksym;
+}
+
 /*
  * /sys/module/foo/sections stuff
  * J. Corbet <corbet@lwn.net>
@@ -1295,7 +1336,34 @@ static inline void remove_notes_attrs(struct module *mod)
 #endif
 
 #ifdef CONFIG_SYSFS
-int module_add_modinfo_attrs(struct module *mod)
+static void add_usage_links(struct module *mod)
+{
+#ifdef CONFIG_MODULE_UNLOAD
+       struct module_use *use;
+       int nowarn;
+
+       mutex_lock(&module_mutex);
+       list_for_each_entry(use, &mod->target_list, target_list) {
+               nowarn = sysfs_create_link(use->target->holders_dir,
+                                          &mod->mkobj.kobj, mod->name);
+       }
+       mutex_unlock(&module_mutex);
+#endif
+}
+
+static void del_usage_links(struct module *mod)
+{
+#ifdef CONFIG_MODULE_UNLOAD
+       struct module_use *use;
+
+       mutex_lock(&module_mutex);
+       list_for_each_entry(use, &mod->target_list, target_list)
+               sysfs_remove_link(use->target->holders_dir, mod->name);
+       mutex_unlock(&module_mutex);
+#endif
+}
+
+static int module_add_modinfo_attrs(struct module *mod)
 {
        struct module_attribute *attr;
        struct module_attribute *temp_attr;
@@ -1321,7 +1389,7 @@ int module_add_modinfo_attrs(struct module *mod)
        return error;
 }
 
-void module_remove_modinfo_attrs(struct module *mod)
+static void module_remove_modinfo_attrs(struct module *mod)
 {
        struct module_attribute *attr;
        int i;
@@ -1337,7 +1405,7 @@ void module_remove_modinfo_attrs(struct module *mod)
        kfree(mod->modinfo_attrs);
 }
 
-int mod_sysfs_init(struct module *mod)
+static int mod_sysfs_init(struct module *mod)
 {
        int err;
        struct kobject *kobj;
@@ -1371,12 +1439,16 @@ out:
        return err;
 }
 
-int mod_sysfs_setup(struct module *mod,
+static int mod_sysfs_setup(struct module *mod,
                           struct kernel_param *kparam,
                           unsigned int num_params)
 {
        int err;
 
+       err = mod_sysfs_init(mod);
+       if (err)
+               goto out;
+
        mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj);
        if (!mod->holders_dir) {
                err = -ENOMEM;
@@ -1391,6 +1463,8 @@ int mod_sysfs_setup(struct module *mod,
        if (err)
                goto out_unreg_param;
 
+       add_usage_links(mod);
+
        kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
        return 0;
 
@@ -1400,6 +1474,7 @@ out_unreg_holders:
        kobject_put(mod->holders_dir);
 out_unreg:
        kobject_put(&mod->mkobj.kobj);
+out:
        return err;
 }
 
@@ -1410,14 +1485,40 @@ static void mod_sysfs_fini(struct module *mod)
 
 #else /* CONFIG_SYSFS */
 
+static inline int mod_sysfs_init(struct module *mod)
+{
+       return 0;
+}
+
+static inline int mod_sysfs_setup(struct module *mod,
+                          struct kernel_param *kparam,
+                          unsigned int num_params)
+{
+       return 0;
+}
+
+static inline int module_add_modinfo_attrs(struct module *mod)
+{
+       return 0;
+}
+
+static inline void module_remove_modinfo_attrs(struct module *mod)
+{
+}
+
 static void mod_sysfs_fini(struct module *mod)
 {
 }
 
+static void del_usage_links(struct module *mod)
+{
+}
+
 #endif /* CONFIG_SYSFS */
 
 static void mod_kobject_remove(struct module *mod)
 {
+       del_usage_links(mod);
        module_remove_modinfo_attrs(mod);
        module_param_sysfs_remove(mod);
        kobject_put(mod->mkobj.drivers_dir);
@@ -1436,13 +1537,15 @@ static int __unlink_module(void *_mod)
        return 0;
 }
 
-/* Free a module, remove from lists, etc (must hold module_mutex). */
+/* Free a module, remove from lists, etc. */
 static void free_module(struct module *mod)
 {
        trace_module_free(mod);
 
        /* Delete from various lists */
+       mutex_lock(&module_mutex);
        stop_machine(__unlink_module, mod, NULL);
+       mutex_unlock(&module_mutex);
        remove_notes_attrs(mod);
        remove_sect_attrs(mod);
        mod_kobject_remove(mod);
@@ -1493,6 +1596,8 @@ EXPORT_SYMBOL_GPL(__symbol_get);
 /*
  * Ensure that an exported symbol [global namespace] does not already exist
  * in the kernel or in some other module's exported symbol table.
+ *
+ * You must hold the module_mutex.
  */
 static int verify_export_symbols(struct module *mod)
 {
@@ -1558,21 +1663,23 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
                        break;
 
                case SHN_UNDEF:
-                       ksym = resolve_symbol(sechdrs, versindex,
-                                             strtab + sym[i].st_name, mod);
+                       ksym = resolve_symbol_wait(sechdrs, versindex,
+                                                  strtab + sym[i].st_name,
+                                                  mod);
                        /* Ok if resolved.  */
-                       if (ksym) {
+                       if (ksym && !IS_ERR(ksym)) {
                                sym[i].st_value = ksym->value;
                                break;
                        }
 
                        /* Ok if weak.  */
-                       if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
+                       if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
                                break;
 
-                       printk(KERN_WARNING "%s: Unknown symbol %s\n",
-                              mod->name, strtab + sym[i].st_name);
-                       ret = -ENOENT;
+                       printk(KERN_WARNING "%s: Unknown symbol %s (err %li)\n",
+                              mod->name, strtab + sym[i].st_name,
+                              PTR_ERR(ksym));
+                       ret = PTR_ERR(ksym) ?: -ENOENT;
                        break;
 
                default:
@@ -1955,16 +2062,24 @@ static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num)
 #endif
 }
 
+static void dynamic_debug_remove(struct _ddebug *debug)
+{
+       if (debug)
+               ddebug_remove_module(debug->modname);
+}
+
 static void *module_alloc_update_bounds(unsigned long size)
 {
        void *ret = module_alloc(size);
 
        if (ret) {
+               mutex_lock(&module_mutex);
                /* Update module bounds. */
                if ((unsigned long)ret < module_addr_min)
                        module_addr_min = (unsigned long)ret;
                if ((unsigned long)ret + size > module_addr_max)
                        module_addr_max = (unsigned long)ret + size;
+               mutex_unlock(&module_mutex);
        }
        return ret;
 }
@@ -2014,6 +2129,9 @@ static noinline struct module *load_module(void __user *umod,
        long err = 0;
        void *ptr = NULL; /* Stops spurious gcc warning */
        unsigned long symoffs, stroffs, *strmap;
+       void __percpu *percpu;
+       struct _ddebug *debug = NULL;
+       unsigned int num_debug = 0;
 
        mm_segment_t old_fs;
 
@@ -2138,11 +2256,6 @@ static noinline struct module *load_module(void __user *umod,
                goto free_mod;
        }
 
-       if (find_module(mod->name)) {
-               err = -EEXIST;
-               goto free_mod;
-       }
-
        mod->state = MODULE_STATE_COMING;
 
        /* Allow arches to frob section contents and sizes.  */
@@ -2158,6 +2271,8 @@ static noinline struct module *load_module(void __user *umod,
                        goto free_mod;
                sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
        }
+       /* Keep this around for failure path. */
+       percpu = mod_percpu(mod);
 
        /* Determine total sizes, and put offsets in sh_entsize.  For now
           this is done generically; there doesn't appear to be any
@@ -2231,11 +2346,6 @@ static noinline struct module *load_module(void __user *umod,
        /* Now we've moved module, initialize linked lists, etc. */
        module_unload_init(mod);
 
-       /* add kobject, so we can reference it. */
-       err = mod_sysfs_init(mod);
-       if (err)
-               goto free_unload;
-
        /* Set up license info based on the info section */
        set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
 
@@ -2360,11 +2470,6 @@ static noinline struct module *load_module(void __user *umod,
                        goto cleanup;
        }
 
-        /* Find duplicate symbols */
-       err = verify_export_symbols(mod);
-       if (err < 0)
-               goto cleanup;
-
        /* Set up and sort exception table */
        mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table",
                                    sizeof(*mod->extable), &mod->num_exentries);
@@ -2379,15 +2484,9 @@ static noinline struct module *load_module(void __user *umod,
        kfree(strmap);
        strmap = NULL;
 
-       if (!mod->taints) {
-               struct _ddebug *debug;
-               unsigned int num_debug;
-
+       if (!mod->taints)
                debug = section_objs(hdr, sechdrs, secstrings, "__verbose",
                                     sizeof(*debug), &num_debug);
-               if (debug)
-                       dynamic_debug_setup(debug, num_debug);
-       }
 
        err = module_finalize(hdr, sechdrs, mod);
        if (err < 0)
@@ -2423,7 +2522,22 @@ static noinline struct module *load_module(void __user *umod,
         * function to insert in a way safe to concurrent readers.
         * The mutex protects against concurrent writers.
         */
+       mutex_lock(&module_mutex);
+       if (find_module(mod->name)) {
+               err = -EEXIST;
+               goto unlock;
+       }
+
+       if (debug)
+               dynamic_debug_setup(debug, num_debug);
+
+       /* Find duplicate symbols */
+       err = verify_export_symbols(mod);
+       if (err < 0)
+               goto ddebug;
+
        list_add_rcu(&mod->list, &modules);
+       mutex_unlock(&module_mutex);
 
        err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL);
        if (err < 0)
@@ -2432,6 +2546,7 @@ static noinline struct module *load_module(void __user *umod,
        err = mod_sysfs_setup(mod, mod->kp, mod->num_kp);
        if (err < 0)
                goto unlink;
+
        add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
        add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
 
@@ -2444,15 +2559,17 @@ static noinline struct module *load_module(void __user *umod,
        return mod;
 
  unlink:
+       mutex_lock(&module_mutex);
        /* Unlink carefully: kallsyms could be walking list. */
        list_del_rcu(&mod->list);
+ ddebug:
+       dynamic_debug_remove(debug);
+ unlock:
+       mutex_unlock(&module_mutex);
        synchronize_sched();
        module_arch_cleanup(mod);
  cleanup:
        free_modinfo(mod);
-       kobject_del(&mod->mkobj.kobj);
-       kobject_put(&mod->mkobj.kobj);
- free_unload:
        module_unload_free(mod);
 #if defined(CONFIG_MODULE_UNLOAD)
        free_percpu(mod->refptr);
@@ -2463,7 +2580,7 @@ static noinline struct module *load_module(void __user *umod,
        module_free(mod, mod->module_core);
        /* mod will be freed with core. Don't access it beyond this line! */
  free_percpu:
-       percpu_modfree(mod);
+       free_percpu(percpu);
  free_mod:
        kfree(args);
        kfree(strmap);
@@ -2499,19 +2616,10 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
        if (!capable(CAP_SYS_MODULE) || modules_disabled)
                return -EPERM;
 
-       /* Only one module load at a time, please */
-       if (mutex_lock_interruptible(&module_mutex) != 0)
-               return -EINTR;
-
        /* Do all the hard work */
        mod = load_module(umod, len, uargs);
-       if (IS_ERR(mod)) {
-               mutex_unlock(&module_mutex);
+       if (IS_ERR(mod))
                return PTR_ERR(mod);
-       }
-
-       /* Drop lock so they can recurse */
-       mutex_unlock(&module_mutex);
 
        blocking_notifier_call_chain(&module_notify_list,
                        MODULE_STATE_COMING, mod);
@@ -2528,9 +2636,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
                module_put(mod);
                blocking_notifier_call_chain(&module_notify_list,
                                             MODULE_STATE_GOING, mod);
-               mutex_lock(&module_mutex);
                free_module(mod);
-               mutex_unlock(&module_mutex);
                wake_up(&module_wq);
                return ret;
        }
index 5c36ea9d55d22ccf5a27d542b262968a13489d57..ca6066a6952e792421c8aff49b57afec5ae2415b 100644 (file)
@@ -99,9 +99,13 @@ config PM_SLEEP_ADVANCED_DEBUG
        depends on PM_ADVANCED_DEBUG
        default n
 
+config SUSPEND_NVS
+       bool
+
 config SUSPEND
        bool "Suspend to RAM and standby"
        depends on PM && ARCH_SUSPEND_POSSIBLE
+       select SUSPEND_NVS if HAS_IOMEM
        default y
        ---help---
          Allow the system to enter sleep states in which main memory is
@@ -130,13 +134,10 @@ config SUSPEND_FREEZER
 
          Turning OFF this setting is NOT recommended! If in doubt, say Y.
 
-config HIBERNATION_NVS
-       bool
-
 config HIBERNATION
        bool "Hibernation (aka 'suspend to disk')"
        depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
-       select HIBERNATION_NVS if HAS_IOMEM
+       select SUSPEND_NVS if HAS_IOMEM
        ---help---
          Enable the suspend to disk (STD) functionality, which is usually
          called "hibernation" in user interfaces.  STD checkpoints the
index 524e058dcf060b4f1acb845a71206082ad80f1a3..f9063c6b185d2917124f06350753ad96e0b184d1 100644 (file)
@@ -10,6 +10,6 @@ obj-$(CONFIG_SUSPEND)         += suspend.o
 obj-$(CONFIG_PM_TEST_SUSPEND)  += suspend_test.o
 obj-$(CONFIG_HIBERNATION)      += hibernate.o snapshot.o swap.o user.o \
                                   block_io.o
-obj-$(CONFIG_HIBERNATION_NVS)  += hibernate_nvs.o
+obj-$(CONFIG_SUSPEND_NVS)      += nvs.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)      += poweroff.o
similarity index 80%
rename from kernel/power/hibernate_nvs.c
rename to kernel/power/nvs.c
index fdcad9ed5a7b00bc0de3ca4a54b1cdd0b6759a1b..1836db60bbb6d56c2ba06f6a0b01b35bc2183fa2 100644 (file)
@@ -15,7 +15,7 @@
 
 /*
  * Platforms, like ACPI, may want us to save some memory used by them during
- * hibernation and to restore the contents of this memory during the subsequent
+ * suspend and to restore the contents of this memory during the subsequent
  * resume.  The code below implements a mechanism allowing us to do that.
  */
 
@@ -30,7 +30,7 @@ struct nvs_page {
 static LIST_HEAD(nvs_list);
 
 /**
- *     hibernate_nvs_register - register platform NVS memory region to save
+ *     suspend_nvs_register - register platform NVS memory region to save
  *     @start - physical address of the region
  *     @size - size of the region
  *
@@ -38,7 +38,7 @@ static LIST_HEAD(nvs_list);
  *     things so that the data from page-aligned addresses in this region will
  *     be copied into separate RAM pages.
  */
-int hibernate_nvs_register(unsigned long start, unsigned long size)
+int suspend_nvs_register(unsigned long start, unsigned long size)
 {
        struct nvs_page *entry, *next;
 
@@ -68,9 +68,9 @@ int hibernate_nvs_register(unsigned long start, unsigned long size)
 }
 
 /**
- *     hibernate_nvs_free - free data pages allocated for saving NVS regions
+ *     suspend_nvs_free - free data pages allocated for saving NVS regions
  */
-void hibernate_nvs_free(void)
+void suspend_nvs_free(void)
 {
        struct nvs_page *entry;
 
@@ -86,16 +86,16 @@ void hibernate_nvs_free(void)
 }
 
 /**
- *     hibernate_nvs_alloc - allocate memory necessary for saving NVS regions
+ *     suspend_nvs_alloc - allocate memory necessary for saving NVS regions
  */
-int hibernate_nvs_alloc(void)
+int suspend_nvs_alloc(void)
 {
        struct nvs_page *entry;
 
        list_for_each_entry(entry, &nvs_list, node) {
                entry->data = (void *)__get_free_page(GFP_KERNEL);
                if (!entry->data) {
-                       hibernate_nvs_free();
+                       suspend_nvs_free();
                        return -ENOMEM;
                }
        }
@@ -103,9 +103,9 @@ int hibernate_nvs_alloc(void)
 }
 
 /**
- *     hibernate_nvs_save - save NVS memory regions
+ *     suspend_nvs_save - save NVS memory regions
  */
-void hibernate_nvs_save(void)
+void suspend_nvs_save(void)
 {
        struct nvs_page *entry;
 
@@ -119,12 +119,12 @@ void hibernate_nvs_save(void)
 }
 
 /**
- *     hibernate_nvs_restore - restore NVS memory regions
+ *     suspend_nvs_restore - restore NVS memory regions
  *
  *     This function is going to be called with interrupts disabled, so it
  *     cannot iounmap the virtual addresses used to access the NVS region.
  */
-void hibernate_nvs_restore(void)
+void suspend_nvs_restore(void)
 {
        struct nvs_page *entry;
 
index 56e7dbb8b996db295b4fc7cdf1b5f11a0409cb0c..f37cb7dd44025ebbe6bcee2f9fc62ef5aeb8974f 100644 (file)
 #include <linux/cpu.h>
 #include <linux/syscalls.h>
 #include <linux/gfp.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
 
 #include "power.h"
 
index d484081425037b5b59ce076c03f524ead13ec37b..f52a8801b7a285fb252ecc6935b55f525813881b 100644 (file)
@@ -306,52 +306,6 @@ static int init_task_group_load = INIT_TASK_GROUP_LOAD;
  */
 struct task_group init_task_group;
 
-/* return group to which a task belongs */
-static inline struct task_group *task_group(struct task_struct *p)
-{
-       struct task_group *tg;
-
-#ifdef CONFIG_CGROUP_SCHED
-       tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id),
-                               struct task_group, css);
-#else
-       tg = &init_task_group;
-#endif
-       return tg;
-}
-
-/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
-static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
-{
-       /*
-        * Strictly speaking this rcu_read_lock() is not needed since the
-        * task_group is tied to the cgroup, which in turn can never go away
-        * as long as there are tasks attached to it.
-        *
-        * However since task_group() uses task_subsys_state() which is an
-        * rcu_dereference() user, this quiets CONFIG_PROVE_RCU.
-        */
-       rcu_read_lock();
-#ifdef CONFIG_FAIR_GROUP_SCHED
-       p->se.cfs_rq = task_group(p)->cfs_rq[cpu];
-       p->se.parent = task_group(p)->se[cpu];
-#endif
-
-#ifdef CONFIG_RT_GROUP_SCHED
-       p->rt.rt_rq  = task_group(p)->rt_rq[cpu];
-       p->rt.parent = task_group(p)->rt_se[cpu];
-#endif
-       rcu_read_unlock();
-}
-
-#else
-
-static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { }
-static inline struct task_group *task_group(struct task_struct *p)
-{
-       return NULL;
-}
-
 #endif /* CONFIG_CGROUP_SCHED */
 
 /* CFS-related fields in a runqueue */
@@ -544,6 +498,8 @@ struct rq {
        struct root_domain *rd;
        struct sched_domain *sd;
 
+       unsigned long cpu_power;
+
        unsigned char idle_at_tick;
        /* For active balancing */
        int post_schedule;
@@ -642,6 +598,49 @@ static inline int cpu_of(struct rq *rq)
 #define cpu_curr(cpu)          (cpu_rq(cpu)->curr)
 #define raw_rq()               (&__raw_get_cpu_var(runqueues))
 
+#ifdef CONFIG_CGROUP_SCHED
+
+/*
+ * Return the group to which this tasks belongs.
+ *
+ * We use task_subsys_state_check() and extend the RCU verification
+ * with lockdep_is_held(&task_rq(p)->lock) because cpu_cgroup_attach()
+ * holds that lock for each task it moves into the cgroup. Therefore
+ * by holding that lock, we pin the task to the current cgroup.
+ */
+static inline struct task_group *task_group(struct task_struct *p)
+{
+       struct cgroup_subsys_state *css;
+
+       css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
+                       lockdep_is_held(&task_rq(p)->lock));
+       return container_of(css, struct task_group, css);
+}
+
+/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
+static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
+{
+#ifdef CONFIG_FAIR_GROUP_SCHED
+       p->se.cfs_rq = task_group(p)->cfs_rq[cpu];
+       p->se.parent = task_group(p)->se[cpu];
+#endif
+
+#ifdef CONFIG_RT_GROUP_SCHED
+       p->rt.rt_rq  = task_group(p)->rt_rq[cpu];
+       p->rt.parent = task_group(p)->rt_se[cpu];
+#endif
+}
+
+#else /* CONFIG_CGROUP_SCHED */
+
+static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { }
+static inline struct task_group *task_group(struct task_struct *p)
+{
+       return NULL;
+}
+
+#endif /* CONFIG_CGROUP_SCHED */
+
 inline void update_rq_clock(struct rq *rq)
 {
        if (!rq->skip_clock_update)
@@ -1255,6 +1254,12 @@ static void sched_avg_update(struct rq *rq)
        s64 period = sched_avg_period();
 
        while ((s64)(rq->clock - rq->age_stamp) > period) {
+               /*
+                * Inline assembly required to prevent the compiler
+                * optimising this loop into a divmod call.
+                * See __iter_div_u64_rem() for another example of this.
+                */
+               asm("" : "+rm" (rq->age_stamp));
                rq->age_stamp += period;
                rq->rt_avg /= 2;
        }
@@ -1499,24 +1504,9 @@ static unsigned long target_load(int cpu, int type)
        return max(rq->cpu_load[type-1], total);
 }
 
-static struct sched_group *group_of(int cpu)
-{
-       struct sched_domain *sd = rcu_dereference_sched(cpu_rq(cpu)->sd);
-
-       if (!sd)
-               return NULL;
-
-       return sd->groups;
-}
-
 static unsigned long power_of(int cpu)
 {
-       struct sched_group *group = group_of(cpu);
-
-       if (!group)
-               return SCHED_LOAD_SCALE;
-
-       return group->cpu_power;
+       return cpu_rq(cpu)->cpu_power;
 }
 
 static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd);
@@ -1673,9 +1663,6 @@ static void update_shares(struct sched_domain *sd)
 
 static void update_h_load(long cpu)
 {
-       if (root_task_group_empty())
-               return;
-
        walk_tg_tree(tg_load_down, tg_nop, (void *)cpu);
 }
 
@@ -1854,8 +1841,8 @@ static void dec_nr_running(struct rq *rq)
 static void set_load_weight(struct task_struct *p)
 {
        if (task_has_rt_policy(p)) {
-               p->se.load.weight = prio_to_weight[0] * 2;
-               p->se.load.inv_weight = prio_to_wmult[0] >> 1;
+               p->se.load.weight = 0;
+               p->se.load.inv_weight = WMULT_CONST;
                return;
        }
 
@@ -2507,7 +2494,16 @@ void sched_fork(struct task_struct *p, int clone_flags)
        if (p->sched_class->task_fork)
                p->sched_class->task_fork(p);
 
+       /*
+        * The child is not yet in the pid-hash so no cgroup attach races,
+        * and the cgroup is pinned to this child due to cgroup_fork()
+        * is ran before sched_fork().
+        *
+        * Silence PROVE_RCU.
+        */
+       rcu_read_lock();
        set_task_cpu(p, cpu);
+       rcu_read_unlock();
 
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
        if (likely(sched_info_on()))
@@ -2877,9 +2873,9 @@ unsigned long nr_iowait(void)
        return sum;
 }
 
-unsigned long nr_iowait_cpu(void)
+unsigned long nr_iowait_cpu(int cpu)
 {
-       struct rq *this = this_rq();
+       struct rq *this = cpu_rq(cpu);
        return atomic_read(&this->nr_iowait);
 }
 
@@ -4478,16 +4474,6 @@ recheck:
        }
 
        if (user) {
-#ifdef CONFIG_RT_GROUP_SCHED
-               /*
-                * Do not allow realtime tasks into groups that have no runtime
-                * assigned.
-                */
-               if (rt_bandwidth_enabled() && rt_policy(policy) &&
-                               task_group(p)->rt_bandwidth.rt_runtime == 0)
-                       return -EPERM;
-#endif
-
                retval = security_task_setscheduler(p, policy, param);
                if (retval)
                        return retval;
@@ -4503,6 +4489,22 @@ recheck:
         * runqueue lock must be held.
         */
        rq = __task_rq_lock(p);
+
+#ifdef CONFIG_RT_GROUP_SCHED
+       if (user) {
+               /*
+                * Do not allow realtime tasks into groups that have no runtime
+                * assigned.
+                */
+               if (rt_bandwidth_enabled() && rt_policy(policy) &&
+                               task_group(p)->rt_bandwidth.rt_runtime == 0) {
+                       __task_rq_unlock(rq);
+                       raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+                       return -EPERM;
+               }
+       }
+#endif
+
        /* recheck policy now with rq lock held */
        if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
                policy = oldpolicy = -1;
@@ -7605,6 +7607,7 @@ void __init sched_init(void)
 #ifdef CONFIG_SMP
                rq->sd = NULL;
                rq->rd = NULL;
+               rq->cpu_power = SCHED_LOAD_SCALE;
                rq->post_schedule = 0;
                rq->active_balance = 0;
                rq->next_balance = jiffies;
index 217e4a9393e42c2f5dfdfae058625601c15e235b..a878b5332daad5d7db16625f298a4e963edac909 100644 (file)
@@ -1225,7 +1225,6 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
        unsigned long this_load, load;
        int idx, this_cpu, prev_cpu;
        unsigned long tl_per_task;
-       unsigned int imbalance;
        struct task_group *tg;
        unsigned long weight;
        int balanced;
@@ -1241,6 +1240,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
         * effect of the currently running task from the load
         * of the current CPU:
         */
+       rcu_read_lock();
        if (sync) {
                tg = task_group(current);
                weight = current->se.load.weight;
@@ -1252,8 +1252,6 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
        tg = task_group(p);
        weight = p->se.load.weight;
 
-       imbalance = 100 + (sd->imbalance_pct - 100) / 2;
-
        /*
         * In low-load situations, where prev_cpu is idle and this_cpu is idle
         * due to the sync cause above having dropped this_load to 0, we'll
@@ -1263,9 +1261,22 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
         * Otherwise check if either cpus are near enough in load to allow this
         * task to be woken on this_cpu.
         */
-       balanced = !this_load ||
-               100*(this_load + effective_load(tg, this_cpu, weight, weight)) <=
-               imbalance*(load + effective_load(tg, prev_cpu, 0, weight));
+       if (this_load) {
+               unsigned long this_eff_load, prev_eff_load;
+
+               this_eff_load = 100;
+               this_eff_load *= power_of(prev_cpu);
+               this_eff_load *= this_load +
+                       effective_load(tg, this_cpu, weight, weight);
+
+               prev_eff_load = 100 + (sd->imbalance_pct - 100) / 2;
+               prev_eff_load *= power_of(this_cpu);
+               prev_eff_load *= load + effective_load(tg, prev_cpu, 0, weight);
+
+               balanced = this_eff_load <= prev_eff_load;
+       } else
+               balanced = true;
+       rcu_read_unlock();
 
        /*
         * If the currently running task will sleep within
@@ -2298,6 +2309,7 @@ static void update_cpu_power(struct sched_domain *sd, int cpu)
        if (!power)
                power = 1;
 
+       cpu_rq(cpu)->cpu_power = power;
        sdg->cpu_power = power;
 }
 
index 825e1126008f374e5d9d2650a5bb29fe2106424d..07b4f1b1a73a9b6a309a3e7fe249c813007b5d17 100644 (file)
@@ -850,7 +850,7 @@ static __init int spawn_ksoftirqd(void)
        void *cpu = (void *)(long)smp_processor_id();
        int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
 
-       BUG_ON(err == NOTIFY_BAD);
+       BUG_ON(err != NOTIFY_OK);
        cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
        register_cpu_notifier(&cpu_nfb);
        return 0;
index b4e7431e7c78996607ef0495d7cb50bc34621d2c..70f8d90331e90359ae555b11d7c5c3ce7fe1a4fb 100644 (file)
@@ -321,7 +321,7 @@ static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb,
 
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_UP_CANCELED:
-       case CPU_DEAD:
+       case CPU_POST_DEAD:
        {
                struct cpu_stop_work *work;
 
index 997080f00e0bcbfca3669af93a97eb5951c17811..d24f761f48769d925692efcbb233a276dad01905 100644 (file)
@@ -1471,12 +1471,12 @@ static struct ctl_table fs_table[] = {
        },
 #endif
        {
-               .procname       = "pipe-max-pages",
-               .data           = &pipe_max_pages,
+               .procname       = "pipe-max-size",
+               .data           = &pipe_max_size,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
-               .extra1         = &two,
+               .proc_handler   = &pipe_proc_fn,
+               .extra1         = &pipe_min_size,
        },
 /*
  * NOTE: do not add new entries to this table unless you have read
index 1d7b9bc1c0340e8deccbc5df1418fd71889d837d..813993b5fb61048f24f876a7247e4f8ac2c861a2 100644 (file)
@@ -154,14 +154,14 @@ static void tick_nohz_update_jiffies(ktime_t now)
  * Updates the per cpu time idle statistics counters
  */
 static void
-update_ts_time_stats(struct tick_sched *ts, ktime_t now, u64 *last_update_time)
+update_ts_time_stats(int cpu, struct tick_sched *ts, ktime_t now, u64 *last_update_time)
 {
        ktime_t delta;
 
        if (ts->idle_active) {
                delta = ktime_sub(now, ts->idle_entrytime);
                ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
-               if (nr_iowait_cpu() > 0)
+               if (nr_iowait_cpu(cpu) > 0)
                        ts->iowait_sleeptime = ktime_add(ts->iowait_sleeptime, delta);
                ts->idle_entrytime = now;
        }
@@ -175,19 +175,19 @@ static void tick_nohz_stop_idle(int cpu, ktime_t now)
 {
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
 
-       update_ts_time_stats(ts, now, NULL);
+       update_ts_time_stats(cpu, ts, now, NULL);
        ts->idle_active = 0;
 
        sched_clock_idle_wakeup_event(0);
 }
 
-static ktime_t tick_nohz_start_idle(struct tick_sched *ts)
+static ktime_t tick_nohz_start_idle(int cpu, struct tick_sched *ts)
 {
        ktime_t now;
 
        now = ktime_get();
 
-       update_ts_time_stats(ts, now, NULL);
+       update_ts_time_stats(cpu, ts, now, NULL);
 
        ts->idle_entrytime = now;
        ts->idle_active = 1;
@@ -216,7 +216,7 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
        if (!tick_nohz_enabled)
                return -1;
 
-       update_ts_time_stats(ts, ktime_get(), last_update_time);
+       update_ts_time_stats(cpu, ts, ktime_get(), last_update_time);
 
        return ktime_to_us(ts->idle_sleeptime);
 }
@@ -242,7 +242,7 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
        if (!tick_nohz_enabled)
                return -1;
 
-       update_ts_time_stats(ts, ktime_get(), last_update_time);
+       update_ts_time_stats(cpu, ts, ktime_get(), last_update_time);
 
        return ktime_to_us(ts->iowait_sleeptime);
 }
@@ -284,7 +284,7 @@ void tick_nohz_stop_sched_tick(int inidle)
         */
        ts->inidle = 1;
 
-       now = tick_nohz_start_idle(ts);
+       now = tick_nohz_start_idle(cpu, ts);
 
        /*
         * If this cpu is offline and it is the one which updates
@@ -315,9 +315,6 @@ void tick_nohz_stop_sched_tick(int inidle)
                goto end;
        }
 
-       if (nohz_ratelimit(cpu))
-               goto end;
-
        ts->idle_calls++;
        /* Read jiffies and the time when jiffies were updated last */
        do {
@@ -328,7 +325,7 @@ void tick_nohz_stop_sched_tick(int inidle)
        } while (read_seqretry(&xtime_lock, seq));
 
        if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) ||
-           arch_needs_cpu(cpu)) {
+           arch_needs_cpu(cpu) || nohz_ratelimit(cpu)) {
                next_jiffies = last_jiffies + 1;
                delta_jiffies = 1;
        } else {
index 2454172a80d3c6131313007d08f91f12eb85c107..ee305c8d4e18eb038a54f0f9aea8eb2f353b1f44 100644 (file)
@@ -1717,7 +1717,7 @@ void __init init_timers(void)
 
        init_timer_stats();
 
-       BUG_ON(err == NOTIFY_BAD);
+       BUG_ON(err != NOTIFY_OK);
        register_cpu_notifier(&timers_nb);
        open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
 }
index 9087d71537ddef84c011b86988e17202b007a291..250ed11d3ed2b83b8e2a87845fe97a7db096b33c 100644 (file)
@@ -113,7 +113,8 @@ static __init int test_atomic64(void)
        r += one;
        BUG_ON(v.counter != r);
 
-#if defined(CONFIG_X86) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(_ASM_GENERIC_ATOMIC64_H)
+#if defined(CONFIG_X86) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || \
+    defined(CONFIG_S390) || defined(_ASM_GENERIC_ATOMIC64_H)
        INIT(onestwos);
        BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1));
        r -= one;
index 3df8eb17a607932bf8091e89c796c338c323c29b..02afc25337284329d23a998e636240d5a41d337d 100644 (file)
@@ -692,7 +692,7 @@ static void ddebug_table_free(struct ddebug_table *dt)
  * Called in response to a module being unloaded.  Removes
  * any ddebug_table's which point at the module.
  */
-int ddebug_remove_module(char *mod_name)
+int ddebug_remove_module(const char *mod_name)
 {
        struct ddebug_table *dt, *nextdt;
        int ret = -ENOENT;
index 736c3b06398e522a7ad3d0ee846d77163436a334..1923f1490e72618b36756b326bbd2e280d71bd49 100644 (file)
@@ -128,7 +128,6 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
                chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
 
                end_bit = (chunk->end_addr - chunk->start_addr) >> order;
-               end_bit -= nbits + 1;
 
                spin_lock_irqsave(&chunk->lock, flags);
                start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit, 0,
index c1a2069017614e6f95a7c2a892fcca1c9c2a7ff1..7f1a4f0acf50e280f5505779bd90f2dda1b97960 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -602,7 +602,7 @@ void *idr_get_next(struct idr *idp, int *nextidp)
        /* find first ent */
        n = idp->layers * IDR_BITS;
        max = 1 << n;
-       p = rcu_dereference(idp->top);
+       p = rcu_dereference_raw(idp->top);
        if (!p)
                return NULL;
 
@@ -610,7 +610,7 @@ void *idr_get_next(struct idr *idp, int *nextidp)
                while (n > 0 && p) {
                        n -= IDR_BITS;
                        *paa++ = p;
-                       p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
+                       p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]);
                }
 
                if (p) {
index 59c15511d58ab9da74ed6d77fed198b666235c6b..b93579504dfaaafee092156c113b36130b0758a7 100644 (file)
@@ -83,6 +83,7 @@ out:
        return ret;
 }
 
+#ifdef CONFIG_NET
 static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
 {
        struct kobject *kobj = data;
@@ -98,6 +99,7 @@ static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
 
        return 0;
 }
+#endif
 
 static int kobj_usermode_filter(struct kobject *kobj)
 {
@@ -378,6 +380,7 @@ static int uevent_net_init(struct net *net)
        if (!ue_sk->sk) {
                printk(KERN_ERR
                       "kobject_uevent: unable to create netlink socket!\n");
+               kfree(ue_sk);
                return -ENODEV;
        }
        mutex_lock(&uevent_sock_mutex);
index c6ece0a5759595bf1ddbbe4a95e4b76713ea4b06..20a8193a7af8ed275667e682fd22101a0e40bb93 100644 (file)
@@ -1370,7 +1370,7 @@ static void memcg_wakeup_oom(struct mem_cgroup *mem)
 
 static void memcg_oom_recover(struct mem_cgroup *mem)
 {
-       if (mem->oom_kill_disable && atomic_read(&mem->oom_lock))
+       if (atomic_read(&mem->oom_lock))
                memcg_wakeup_oom(mem);
 }
 
@@ -3781,6 +3781,8 @@ static int mem_cgroup_oom_control_write(struct cgroup *cgrp,
                return -EINVAL;
        }
        mem->oom_kill_disable = val;
+       if (!val)
+               memcg_oom_recover(mem);
        cgroup_unlock();
        return 0;
 }
index 5d6fb339de038945424733d5128846a1a1a7e352..5bc0a96beb51b550b69389998fc3e09053ee5a2f 100644 (file)
@@ -2094,7 +2094,7 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
                NODEMASK_SCRATCH(scratch);
 
                if (!scratch)
-                       return;
+                       goto put_mpol;
                /* contextualize the tmpfs mount point mempolicy */
                new = mpol_new(mpol->mode, mpol->flags, &mpol->w.user_nodemask);
                if (IS_ERR(new))
@@ -2103,19 +2103,20 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
                task_lock(current);
                ret = mpol_set_nodemask(new, &mpol->w.user_nodemask, scratch);
                task_unlock(current);
-               mpol_put(mpol); /* drop our ref on sb mpol */
                if (ret)
-                       goto put_free;
+                       goto put_new;
 
                /* Create pseudo-vma that contains just the policy */
                memset(&pvma, 0, sizeof(struct vm_area_struct));
                pvma.vm_end = TASK_SIZE;        /* policy covers entire file */
                mpol_set_shared_policy(sp, &pvma, new); /* adds ref */
 
-put_free:
+put_new:
                mpol_put(new);                  /* drop initial ref */
 free_scratch:
                NODEMASK_SCRATCH_FREE(scratch);
+put_mpol:
+               mpol_put(mpol); /* drop our incoming ref on sb mpol */
        }
 }
 
index b289310e2c899ba472ea1f7a92a01b908f549f18..54f28bd493d3f6a04f437d6294d54a322daa4603 100644 (file)
@@ -597,7 +597,7 @@ static void balance_dirty_pages(struct address_space *mapping,
            (!laptop_mode && ((global_page_state(NR_FILE_DIRTY)
                               + global_page_state(NR_UNSTABLE_NFS))
                                          > background_thresh)))
-               bdi_start_writeback(bdi, NULL, 0, 0);
+               bdi_start_background_writeback(bdi);
 }
 
 void set_page_dirty_balance(struct page *page, int page_mkwrite)
@@ -705,9 +705,8 @@ void laptop_mode_timer_fn(unsigned long data)
         * We want to write everything out, not just down to the dirty
         * threshold
         */
-
        if (bdi_has_dirty_io(&q->backing_dev_info))
-               bdi_start_writeback(&q->backing_dev_info, NULL, nr_pages, 0);
+               bdi_start_writeback(&q->backing_dev_info, nr_pages);
 }
 
 /*
@@ -835,7 +834,6 @@ int write_cache_pages(struct address_space *mapping,
        pgoff_t done_index;
        int cycled;
        int range_whole = 0;
-       long nr_to_write = wbc->nr_to_write;
 
        pagevec_init(&pvec, 0);
        if (wbc->range_cyclic) {
@@ -852,7 +850,22 @@ int write_cache_pages(struct address_space *mapping,
                if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
                        range_whole = 1;
                cycled = 1; /* ignore range_cyclic tests */
+
+               /*
+                * If this is a data integrity sync, cap the writeback to the
+                * current end of file. Any extension to the file that occurs
+                * after this is a new write and we don't need to write those
+                * pages out to fulfil our data integrity requirements. If we
+                * try to write them out, we can get stuck in this scan until
+                * the concurrent writer stops adding dirty pages and extending
+                * EOF.
+                */
+               if (wbc->sync_mode == WB_SYNC_ALL &&
+                   wbc->range_end == LLONG_MAX) {
+                       end = i_size_read(mapping->host) >> PAGE_CACHE_SHIFT;
+               }
        }
+
 retry:
        done_index = index;
        while (!done && (index <= end)) {
@@ -935,11 +948,10 @@ continue_unlock:
                                        done = 1;
                                        break;
                                }
-                       }
+                       }
 
-                       if (nr_to_write > 0) {
-                               nr_to_write--;
-                               if (nr_to_write == 0 &&
+                       if (wbc->nr_to_write > 0) {
+                               if (--wbc->nr_to_write == 0 &&
                                    wbc->sync_mode == WB_SYNC_NONE) {
                                        /*
                                         * We stop writing back only if we are
@@ -970,11 +982,8 @@ continue_unlock:
                end = writeback_index - 1;
                goto retry;
        }
-       if (!wbc->no_nrwrite_index_update) {
-               if (wbc->range_cyclic || (range_whole && nr_to_write > 0))
-                       mapping->writeback_index = done_index;
-               wbc->nr_to_write = nr_to_write;
-       }
+       if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
+               mapping->writeback_index = done_index;
 
        return ret;
 }
index 39f7dfd59585a118f4a8c6be480bf3b866a50f25..6470e7710231a84d75dc793831bc9f92e178f8bb 100644 (file)
@@ -229,8 +229,8 @@ static int __maybe_unused pcpu_page_idx(unsigned int cpu, int page_idx)
        return pcpu_unit_map[cpu] * pcpu_unit_pages + page_idx;
 }
 
-static unsigned long __maybe_unused pcpu_chunk_addr(struct pcpu_chunk *chunk,
-                                               unsigned int cpu, int page_idx)
+static unsigned long pcpu_chunk_addr(struct pcpu_chunk *chunk,
+                                    unsigned int cpu, int page_idx)
 {
        return (unsigned long)chunk->base_addr + pcpu_unit_offsets[cpu] +
                (page_idx << PAGE_SHIFT);
@@ -978,7 +978,32 @@ bool is_kernel_percpu_address(unsigned long addr)
  */
 phys_addr_t per_cpu_ptr_to_phys(void *addr)
 {
-       if (pcpu_addr_in_first_chunk(addr)) {
+       void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr);
+       bool in_first_chunk = false;
+       unsigned long first_start, first_end;
+       unsigned int cpu;
+
+       /*
+        * The following test on first_start/end isn't strictly
+        * necessary but will speed up lookups of addresses which
+        * aren't in the first chunk.
+        */
+       first_start = pcpu_chunk_addr(pcpu_first_chunk, pcpu_first_unit_cpu, 0);
+       first_end = pcpu_chunk_addr(pcpu_first_chunk, pcpu_last_unit_cpu,
+                                   pcpu_unit_pages);
+       if ((unsigned long)addr >= first_start &&
+           (unsigned long)addr < first_end) {
+               for_each_possible_cpu(cpu) {
+                       void *start = per_cpu_ptr(base, cpu);
+
+                       if (addr >= start && addr < start + pcpu_unit_size) {
+                               in_first_chunk = true;
+                               break;
+                       }
+               }
+       }
+
+       if (in_first_chunk) {
                if ((unsigned long)addr < VMALLOC_START ||
                    (unsigned long)addr >= VMALLOC_END)
                        return __pa(addr);
@@ -1086,7 +1111,7 @@ struct pcpu_alloc_info * __init pcpu_build_alloc_info(
        static int group_map[NR_CPUS] __initdata;
        static int group_cnt[NR_CPUS] __initdata;
        const size_t static_size = __per_cpu_end - __per_cpu_start;
-       int group_cnt_max = 0, nr_groups = 1, nr_units = 0;
+       int nr_groups = 1, nr_units = 0;
        size_t size_sum, min_unit_size, alloc_size;
        int upa, max_upa, uninitialized_var(best_upa);  /* units_per_alloc */
        int last_allocs, group, unit;
@@ -1096,7 +1121,7 @@ struct pcpu_alloc_info * __init pcpu_build_alloc_info(
 
        /* this function may be called multiple times */
        memset(group_map, 0, sizeof(group_map));
-       memset(group_cnt, 0, sizeof(group_map));
+       memset(group_cnt, 0, sizeof(group_cnt));
 
        /*
         * Determine min_unit_size, alloc_size and max_upa such that
@@ -1130,7 +1155,6 @@ struct pcpu_alloc_info * __init pcpu_build_alloc_info(
                }
                group_map[cpu] = group;
                group_cnt[group]++;
-               group_cnt_max = max(group_cnt_max, group_cnt[group]);
        }
 
        /*
index 7e5030ae18ffd07ab19f070939f357fff3816ab9..f65f84062db554ed2b3e9452cc787f8ab4f1b0d3 100644 (file)
@@ -764,10 +764,11 @@ done2:
 static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
+       loff_t newsize = attr->ia_size;
        int error;
 
-       if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
-               loff_t newsize = attr->ia_size;
+       if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)
+                                       && newsize != inode->i_size) {
                struct page *page = NULL;
 
                if (newsize < inode->i_size) {
index 915dceb487c11b1f1783df86908ba5e6e7317769..9c7e57cc63a34f7231b77a7d8b395d3157a34ba6 100644 (file)
@@ -1724,13 +1724,13 @@ static void shrink_zone(int priority, struct zone *zone,
  * If a zone is deemed to be full of pinned pages then just give it a light
  * scan then give up on it.
  */
-static int shrink_zones(int priority, struct zonelist *zonelist,
+static bool shrink_zones(int priority, struct zonelist *zonelist,
                                        struct scan_control *sc)
 {
        enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask);
        struct zoneref *z;
        struct zone *zone;
-       int progress = 0;
+       bool all_unreclaimable = true;
 
        for_each_zone_zonelist_nodemask(zone, z, zonelist, high_zoneidx,
                                        sc->nodemask) {
@@ -1757,9 +1757,9 @@ static int shrink_zones(int priority, struct zonelist *zonelist,
                }
 
                shrink_zone(priority, zone, sc);
-               progress = 1;
+               all_unreclaimable = false;
        }
-       return progress;
+       return all_unreclaimable;
 }
 
 /*
@@ -1782,7 +1782,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                                        struct scan_control *sc)
 {
        int priority;
-       unsigned long ret = 0;
+       bool all_unreclaimable;
        unsigned long total_scanned = 0;
        struct reclaim_state *reclaim_state = current->reclaim_state;
        unsigned long lru_pages = 0;
@@ -1813,7 +1813,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                sc->nr_scanned = 0;
                if (!priority)
                        disable_swap_token();
-               ret = shrink_zones(priority, zonelist, sc);
+               all_unreclaimable = shrink_zones(priority, zonelist, sc);
                /*
                 * Don't shrink slabs when reclaiming memory from
                 * over limit cgroups
@@ -1826,10 +1826,8 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                        }
                }
                total_scanned += sc->nr_scanned;
-               if (sc->nr_reclaimed >= sc->nr_to_reclaim) {
-                       ret = sc->nr_reclaimed;
+               if (sc->nr_reclaimed >= sc->nr_to_reclaim)
                        goto out;
-               }
 
                /*
                 * Try to write back as many pages as we just scanned.  This
@@ -1849,9 +1847,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                    priority < DEF_PRIORITY - 2)
                        congestion_wait(BLK_RW_ASYNC, HZ/10);
        }
-       /* top priority shrink_zones still had more to do? don't OOM, then */
-       if (ret && scanning_global_lru(sc))
-               ret = sc->nr_reclaimed;
+
 out:
        /*
         * Now that we've scanned all the zones at this priority level, note
@@ -1877,7 +1873,14 @@ out:
        delayacct_freepages_end();
        put_mems_allowed();
 
-       return ret;
+       if (sc->nr_reclaimed)
+               return sc->nr_reclaimed;
+
+       /* top priority shrink_zones still had more to do? don't OOM, then */
+       if (scanning_global_lru(sc) && !all_unreclaimable)
+               return 1;
+
+       return 0;
 }
 
 unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
index bd537fc10254c9fbb6cf3872e8488bba1809781b..50f58f5f1c3491f775a5ac6c97ea32c5c5b23674 100644 (file)
@@ -12,7 +12,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
                return NET_RX_DROP;
 
        if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
-               goto drop;
+               skb->deliver_no_wcard = 1;
 
        skb->skb_iif = skb->dev->ifindex;
        __vlan_hwaccel_put_tag(skb, vlan_tci);
@@ -84,7 +84,7 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
        struct sk_buff *p;
 
        if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
-               goto drop;
+               skb->deliver_no_wcard = 1;
 
        skb->skb_iif = skb->dev->ifindex;
        __vlan_hwaccel_put_tag(skb, vlan_tci);
index 55be90826f5fd1317f961b9fbabb3f3b989f380e..52984267781782cd78aa0bd7bc3d38280745c1b1 100644 (file)
@@ -708,7 +708,8 @@ static int vlan_dev_init(struct net_device *dev)
        netif_carrier_off(dev);
 
        /* IFF_BROADCAST|IFF_MULTICAST; ??? */
-       dev->flags  = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI);
+       dev->flags  = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
+                                         IFF_MASTER | IFF_SLAVE);
        dev->iflink = real_dev->ifindex;
        dev->state  = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
                                          (1<<__LINK_STATE_DORMANT))) |
index 0faad5ce6dc480efe1928c1c60728e14b4093b92..8c100c9dae2833bcf3963a2cc4c8a9a2fcbdc064 100644 (file)
@@ -104,6 +104,8 @@ static void bnep_net_set_mc_list(struct net_device *dev)
                                break;
                        memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
                        memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
+
+                       i++;
                }
                r->len = htons(skb->len - len);
        }
index 26637439965bef745542f7baa4242d5249a33d9d..b01dde35a69ed3f1cecf30ebe604cc1808d72a69 100644 (file)
@@ -128,7 +128,7 @@ void br_fdb_cleanup(unsigned long _data)
 {
        struct net_bridge *br = (struct net_bridge *)_data;
        unsigned long delay = hold_time(br);
-       unsigned long next_timer = jiffies + br->forward_delay;
+       unsigned long next_timer = jiffies + br->ageing_time;
        int i;
 
        spin_lock_bh(&br->hash_lock);
@@ -149,9 +149,7 @@ void br_fdb_cleanup(unsigned long _data)
        }
        spin_unlock_bh(&br->hash_lock);
 
-       /* Add HZ/4 to ensure we round the jiffies upwards to be after the next
-        * timer, otherwise we might round down and will have no-op run. */
-       mod_timer(&br->gc_timer, round_jiffies(next_timer + HZ/4));
+       mod_timer(&br->gc_timer, round_jiffies_up(next_timer));
 }
 
 /* Completely flush all dynamic entries in forwarding database.*/
index a98ef13930979a129a8d0195e5a94dee3ec7bd2a..a4e72a89e4ffc4eae7a2e7e09963bd0fb58e26a4 100644 (file)
@@ -140,10 +140,10 @@ static int deliver_clone(const struct net_bridge_port *prev,
                         void (*__packet_hook)(const struct net_bridge_port *p,
                                               struct sk_buff *skb))
 {
+       struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
+
        skb = skb_clone(skb, GFP_ATOMIC);
        if (!skb) {
-               struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
-
                dev->stats.tx_dropped++;
                return -ENOMEM;
        }
index cd2830fec9351322156e941c9d7043418ea549a4..fd27b172fb5d444ffdf5664312f0b0c86b4836cd 100644 (file)
@@ -83,7 +83,7 @@ static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt)
        if (!cfsrvl_ready(service, &ret))
                return ret;
 
-       if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
+       if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
                pr_err("CAIF: %s():Packet too large - size=%d\n",
                        __func__, cfpkt_getlen(pkt));
                return -EOVERFLOW;
index cb4325a3dc83184f4a4f8e382dbec6b7ac6c21f2..965c5baace40b10c401c8fff3ecaaacb612c0aa6 100644 (file)
@@ -59,16 +59,18 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt)
        u8 stx = CFSERL_STX;
        int ret;
        u16 expectlen = 0;
+
        caif_assert(newpkt != NULL);
        spin_lock(&layr->sync);
 
        if (layr->incomplete_frm != NULL) {
-
                layr->incomplete_frm =
                    cfpkt_append(layr->incomplete_frm, newpkt, expectlen);
                pkt = layr->incomplete_frm;
-               if (pkt == NULL)
+               if (pkt == NULL) {
+                       spin_unlock(&layr->sync);
                        return -ENOMEM;
+               }
        } else {
                pkt = newpkt;
        }
index 0fd827f494919caa44926264baa885ea409df776..e04f7d964e83ea8d0c88308bb0fcd2e3dd9dfbd6 100644 (file)
@@ -84,7 +84,7 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt)
                return ret;
        caif_assert(layr->dn != NULL);
        caif_assert(layr->dn->transmit != NULL);
-       if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
+       if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
                pr_warning("CAIF: %s(): Packet too large - size=%d\n",
                           __func__, cfpkt_getlen(pkt));
                return -EOVERFLOW;
index 1845b08c624e1fa4c9dd398f4b61c2963dbfc1f2..2b3bf53bc687aab3c9cfb32cce902eaebb3c18da 100644 (file)
@@ -2253,11 +2253,9 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
        if (skb_rx_queue_recorded(skb)) {
                u16 index = skb_get_rx_queue(skb);
                if (unlikely(index >= dev->num_rx_queues)) {
-                       if (net_ratelimit()) {
-                               pr_warning("%s received packet on queue "
-                                       "%u, but number of RX queues is %u\n",
-                                       dev->name, index, dev->num_rx_queues);
-                       }
+                       WARN_ONCE(dev->num_rx_queues > 1, "%s received packet "
+                               "on queue %u, but number of RX queues is %u\n",
+                               dev->name, index, dev->num_rx_queues);
                        goto done;
                }
                rxqueue = dev->_rx + index;
@@ -2795,7 +2793,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
        struct net_device *orig_dev;
        struct net_device *master;
        struct net_device *null_or_orig;
-       struct net_device *null_or_bond;
+       struct net_device *orig_or_bond;
        int ret = NET_RX_DROP;
        __be16 type;
 
@@ -2812,13 +2810,24 @@ static int __netif_receive_skb(struct sk_buff *skb)
        if (!skb->skb_iif)
                skb->skb_iif = skb->dev->ifindex;
 
+       /*
+        * bonding note: skbs received on inactive slaves should only
+        * be delivered to pkt handlers that are exact matches.  Also
+        * the deliver_no_wcard flag will be set.  If packet handlers
+        * are sensitive to duplicate packets these skbs will need to
+        * be dropped at the handler.  The vlan accel path may have
+        * already set the deliver_no_wcard flag.
+        */
        null_or_orig = NULL;
        orig_dev = skb->dev;
        master = ACCESS_ONCE(orig_dev->master);
-       if (master) {
-               if (skb_bond_should_drop(skb, master))
+       if (skb->deliver_no_wcard)
+               null_or_orig = orig_dev;
+       else if (master) {
+               if (skb_bond_should_drop(skb, master)) {
+                       skb->deliver_no_wcard = 1;
                        null_or_orig = orig_dev; /* deliver only exact match */
-               else
+               else
                        skb->dev = master;
        }
 
@@ -2868,10 +2877,10 @@ ncls:
         * device that may have registered for a specific ptype.  The
         * handler may have to adjust skb->dev and orig_dev.
         */
-       null_or_bond = NULL;
+       orig_or_bond = orig_dev;
        if ((skb->dev->priv_flags & IFF_802_1Q_VLAN) &&
            (vlan_dev_real_dev(skb->dev)->priv_flags & IFF_BONDING)) {
-               null_or_bond = vlan_dev_real_dev(skb->dev);
+               orig_or_bond = vlan_dev_real_dev(skb->dev);
        }
 
        type = skb->protocol;
@@ -2879,7 +2888,7 @@ ncls:
                        &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
                if (ptype->type == type && (ptype->dev == null_or_orig ||
                     ptype->dev == skb->dev || ptype->dev == orig_dev ||
-                    ptype->dev == null_or_bond)) {
+                    ptype->dev == orig_or_bond)) {
                        if (pt_prev)
                                ret = deliver_skb(skb, pt_prev, orig_dev);
                        pt_prev = ptype;
index cf8e70392fe0938acb4b8b88fa8bc74dbeaed584..785e5276a300e6f14c634e785eb1be8e0633c18e 100644 (file)
@@ -107,6 +107,7 @@ static DEFINE_RWLOCK(est_lock);
 
 /* Protects against soft lockup during large deletion */
 static struct rb_root est_root = RB_ROOT;
+static DEFINE_SPINLOCK(est_tree_lock);
 
 static void est_timer(unsigned long arg)
 {
@@ -201,7 +202,6 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats
  *
  * Returns 0 on success or a negative error code.
  *
- * NOTE: Called under rtnl_mutex
  */
 int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
                      struct gnet_stats_rate_est *rate_est,
@@ -232,6 +232,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
        est->last_packets = bstats->packets;
        est->avpps = rate_est->pps<<10;
 
+       spin_lock(&est_tree_lock);
        if (!elist[idx].timer.function) {
                INIT_LIST_HEAD(&elist[idx].list);
                setup_timer(&elist[idx].timer, est_timer, idx);
@@ -242,6 +243,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
 
        list_add_rcu(&est->list, &elist[idx].list);
        gen_add_node(est);
+       spin_unlock(&est_tree_lock);
 
        return 0;
 }
@@ -261,13 +263,13 @@ static void __gen_kill_estimator(struct rcu_head *head)
  *
  * Removes the rate estimator specified by &bstats and &rate_est.
  *
- * NOTE: Called under rtnl_mutex
  */
 void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
                        struct gnet_stats_rate_est *rate_est)
 {
        struct gen_estimator *e;
 
+       spin_lock(&est_tree_lock);
        while ((e = gen_find_node(bstats, rate_est))) {
                rb_erase(&e->node, &est_root);
 
@@ -278,6 +280,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
                list_del_rcu(&e->list);
                call_rcu(&e->e_rcu, __gen_kill_estimator);
        }
+       spin_unlock(&est_tree_lock);
 }
 EXPORT_SYMBOL(gen_kill_estimator);
 
@@ -312,8 +315,14 @@ EXPORT_SYMBOL(gen_replace_estimator);
 bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
                          const struct gnet_stats_rate_est *rate_est)
 {
+       bool res;
+
        ASSERT_RTNL();
 
-       return gen_find_node(bstats, rate_est) != NULL;
+       spin_lock(&est_tree_lock);
+       res = gen_find_node(bstats, rate_est) != NULL;
+       spin_unlock(&est_tree_lock);
+
+       return res;
 }
 EXPORT_SYMBOL(gen_estimator_active);
index 2ad68da418df6a6d6d4ae81db9e78d4a8f6ae981..1dacd7ba8dbb1d4c2e5e6e9f623b3806e202f0ee 100644 (file)
@@ -2170,7 +2170,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
        end_time = ktime_now();
 
        pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time));
-       pkt_dev->next_tx = ktime_add_ns(end_time, pkt_dev->delay);
+       pkt_dev->next_tx = ktime_add_ns(spin_until, pkt_dev->delay);
 }
 
 static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
index f8abf68e3988f7cd5b4a83eb6a18b3ae25d52afd..34432b4e96bb288931e8b6ebf2d8d78b5c6589c5 100644 (file)
@@ -482,22 +482,22 @@ EXPORT_SYMBOL(consume_skb);
  *     reference count dropping and cleans up the skbuff as if it
  *     just came from __alloc_skb().
  */
-int skb_recycle_check(struct sk_buff *skb, int skb_size)
+bool skb_recycle_check(struct sk_buff *skb, int skb_size)
 {
        struct skb_shared_info *shinfo;
 
        if (irqs_disabled())
-               return 0;
+               return false;
 
        if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE)
-               return 0;
+               return false;
 
        skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
        if (skb_end_pointer(skb) - skb->head < skb_size)
-               return 0;
+               return false;
 
        if (skb_shared(skb) || skb_cloned(skb))
-               return 0;
+               return false;
 
        skb_release_head_state(skb);
 
@@ -509,7 +509,7 @@ int skb_recycle_check(struct sk_buff *skb, int skb_size)
        skb->data = skb->head + NET_SKB_PAD;
        skb_reset_tail_pointer(skb);
 
-       return 1;
+       return true;
 }
 EXPORT_SYMBOL(skb_recycle_check);
 
@@ -532,6 +532,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
        new->ip_summed          = old->ip_summed;
        skb_copy_queue_mapping(new, old);
        new->priority           = old->priority;
+       new->deliver_no_wcard   = old->deliver_no_wcard;
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
        new->ipvs_property      = old->ipvs_property;
 #endif
@@ -569,7 +570,6 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
        C(len);
        C(data_len);
        C(mac_len);
-       C(rxhash);
        n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
        n->cloned = 1;
        n->nohdr = 0;
@@ -2965,6 +2965,34 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
 }
 EXPORT_SYMBOL_GPL(skb_cow_data);
 
+static void sock_rmem_free(struct sk_buff *skb)
+{
+       struct sock *sk = skb->sk;
+
+       atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
+}
+
+/*
+ * Note: We dont mem charge error packets (no sk_forward_alloc changes)
+ */
+int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
+{
+       if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
+           (unsigned)sk->sk_rcvbuf)
+               return -ENOMEM;
+
+       skb_orphan(skb);
+       skb->sk = sk;
+       skb->destructor = sock_rmem_free;
+       atomic_add(skb->truesize, &sk->sk_rmem_alloc);
+
+       skb_queue_tail(&sk->sk_error_queue, skb);
+       if (!sock_flag(sk, SOCK_DEAD))
+               sk->sk_data_ready(sk, skb->len);
+       return 0;
+}
+EXPORT_SYMBOL(sock_queue_err_skb);
+
 void skb_tstamp_tx(struct sk_buff *orig_skb,
                struct skb_shared_hwtstamps *hwtstamps)
 {
@@ -2996,7 +3024,9 @@ void skb_tstamp_tx(struct sk_buff *orig_skb,
        memset(serr, 0, sizeof(*serr));
        serr->ee.ee_errno = ENOMSG;
        serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
+
        err = sock_queue_err_skb(sk, skb);
+
        if (err)
                kfree_skb(skb);
 }
index 8e3a1fd938ab3c2f18a8f9884598858b2020cd88..7c3a7d19124995fd89034a4db2254566aab4cdfd 100644 (file)
@@ -303,7 +303,7 @@ config ARPD
          If unsure, say N.
 
 config SYN_COOKIES
-       bool "IP: TCP syncookie support (disabled per default)"
+       bool "IP: TCP syncookie support"
        ---help---
          Normal TCP/IP networking is open to an attack known as "SYN
          flooding". This denial-of-service attack prevents legitimate remote
@@ -328,13 +328,13 @@ config SYN_COOKIES
          server is really overloaded. If this happens frequently better turn
          them off.
 
-         If you say Y here, note that SYN cookies aren't enabled by default;
-         you can enable them by saying Y to "/proc file system support" and
+         If you say Y here, you can disable SYN cookies at run time by
+         saying Y to "/proc file system support" and
          "Sysctl support" below and executing the command
 
-         echo 1 >/proc/sys/net/ipv4/tcp_syncookies
+         echo 0 > /proc/sys/net/ipv4/tcp_syncookies
 
-         at boot time after the /proc file system has been mounted.
+         after the /proc file system has been mounted.
 
          If unsure, say N.
 
index 9a4a6c96cb0d634414691da197bf9e337fe18f81..041d41df1224eec36f214cd649467e423be5de96 100644 (file)
@@ -873,8 +873,10 @@ int ip_append_data(struct sock *sk,
            !exthdrlen)
                csummode = CHECKSUM_PARTIAL;
 
+       skb = skb_peek_tail(&sk->sk_write_queue);
+
        inet->cork.length += length;
-       if (((length> mtu) || !skb_queue_empty(&sk->sk_write_queue)) &&
+       if (((length > mtu) || (skb && skb_is_gso(skb))) &&
            (sk->sk_protocol == IPPROTO_UDP) &&
            (rt->u.dst.dev->features & NETIF_F_UFO)) {
                err = ip_ufo_append_data(sk, getfrag, from, length, hh_len,
@@ -892,7 +894,7 @@ int ip_append_data(struct sock *sk,
         * adding appropriate IP header.
         */
 
-       if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
+       if (!skb)
                goto alloc_new_skb;
 
        while (length > 0) {
@@ -1121,7 +1123,8 @@ ssize_t   ip_append_page(struct sock *sk, struct page *page,
                return -EINVAL;
 
        inet->cork.length += size;
-       if ((sk->sk_protocol == IPPROTO_UDP) &&
+       if ((size + skb->len > mtu) &&
+           (sk->sk_protocol == IPPROTO_UDP) &&
            (rt->u.dst.dev->features & NETIF_F_UFO)) {
                skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
index 856123fe32f98c97e3364a322fe9899d4b8d1359..757f25eb9b4b2404ebebc6c4422b4ad1693ea227 100644 (file)
@@ -267,8 +267,10 @@ static void __net_exit ipmr_rules_exit(struct net *net)
 {
        struct mr_table *mrt, *next;
 
-       list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list)
+       list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) {
+               list_del(&mrt->list);
                kfree(mrt);
+       }
        fib_rules_unregister(net->ipv4.mr_rules_ops);
 }
 #else
index 63958f3394a5d0fbe67e675ee72a10b9d27446cd..4b6c5ca610fc0a463db4995e8b58393916e0a35c 100644 (file)
@@ -336,7 +336,7 @@ ipt_do_table(struct sk_buff *skb,
        cpu        = smp_processor_id();
        table_base = private->entries[cpu];
        jumpstack  = (struct ipt_entry **)private->jumpstack[cpu];
-       stackptr   = &private->stackptr[cpu];
+       stackptr   = per_cpu_ptr(private->stackptr, cpu);
        origptr    = *stackptr;
 
        e = get_entry(table_base, private->hook_entry[hook]);
index 5c24db4a3c91a54d7d6b3b86e8d4d906999d7d76..9f6b22206c527263fea9c56727967afd92b773bb 100644 (file)
@@ -347,7 +347,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
                                               { .sport = th->dest,
                                                 .dport = th->source } } };
                security_req_classify_flow(req, &fl);
-               if (ip_route_output_key(&init_net, &rt, &fl)) {
+               if (ip_route_output_key(sock_net(sk), &rt, &fl)) {
                        reqsk_free(req);
                        goto out;
                }
index c209e054a634ed5b07f9b6d8374006887a2c2085..377bc93493712f3037ae1cb2e12eb6e421366a4e 100644 (file)
@@ -126,8 +126,8 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
                 * calculate 2^fract in a <<7 value.
                 */
                is_slowstart = 1;
-               increment = ((1 << ca->rho) * hybla_fraction(rho_fractions))
-                       - 128;
+               increment = ((1 << min(ca->rho, 16U)) *
+                       hybla_fraction(rho_fractions)) - 128;
        } else {
                /*
                 * congestion avoidance
index 3e6dafcb1071663c2e0590da7c379b6b324bbe0f..548d575e6cc684673ef9c7a7a613e2f444ec509c 100644 (file)
@@ -2639,7 +2639,7 @@ static void DBGUNDO(struct sock *sk, const char *msg)
        if (sk->sk_family == AF_INET) {
                printk(KERN_DEBUG "Undo %s %pI4/%u c%u l%u ss%u/%u p%u\n",
                       msg,
-                      &inet->daddr, ntohs(inet->dport),
+                      &inet->inet_daddr, ntohs(inet->inet_dport),
                       tp->snd_cwnd, tcp_left_out(tp),
                       tp->snd_ssthresh, tp->prior_ssthresh,
                       tp->packets_out);
@@ -2649,7 +2649,7 @@ static void DBGUNDO(struct sock *sk, const char *msg)
                struct ipv6_pinfo *np = inet6_sk(sk);
                printk(KERN_DEBUG "Undo %s %pI6/%u c%u l%u ss%u/%u p%u\n",
                       msg,
-                      &np->daddr, ntohs(inet->dport),
+                      &np->daddr, ntohs(inet->inet_dport),
                       tp->snd_cwnd, tcp_left_out(tp),
                       tp->snd_ssthresh, tp->prior_ssthresh,
                       tp->packets_out);
index 202cf09c4cd4be9f8a556d2740a51ca4bba96e56..fe193e53af447f49fe05a8cba7b495c38f421be2 100644 (file)
@@ -1555,6 +1555,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
 #endif
 
        if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
+               sock_rps_save_rxhash(sk, skb->rxhash);
                TCP_CHECK_TIMER(sk);
                if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
                        rsk = sk;
@@ -1579,7 +1580,9 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
                        }
                        return 0;
                }
-       }
+       } else
+               sock_rps_save_rxhash(sk, skb->rxhash);
+
 
        TCP_CHECK_TIMER(sk);
        if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) {
@@ -1672,8 +1675,6 @@ process:
 
        skb->dev = NULL;
 
-       sock_rps_save_rxhash(sk, skb->rxhash);
-
        bh_lock_sock_nested(sk);
        ret = 0;
        if (!sock_owned_by_user(sk)) {
index 58585748bdac7cc7be011c090409e37f492573a4..eec4ff456e332e0b086d5451478fa5874213e0d1 100644 (file)
@@ -633,9 +633,9 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
        if (!inet->recverr) {
                if (!harderr || sk->sk_state != TCP_ESTABLISHED)
                        goto out;
-       } else {
+       } else
                ip_icmp_error(sk, skb, err, uh->dest, info, (u8 *)(uh+1));
-       }
+
        sk->sk_err = err;
        sk->sk_error_report(sk);
 out:
index ce7992982557d8cc28037bbb6388ede8f0e62d46..03e62f94ff8efb35a5c865322d72e623b539eeef 100644 (file)
@@ -483,7 +483,7 @@ route_done:
                              np->tclass, NULL, &fl, (struct rt6_info*)dst,
                              MSG_DONTWAIT, np->dontfrag);
        if (err) {
-               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
+               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
                ip6_flush_pending_frames(sk);
                goto out_put;
        }
@@ -565,7 +565,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
                                np->dontfrag);
 
        if (err) {
-               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
+               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
                ip6_flush_pending_frames(sk);
                goto out_put;
        }
index 073071f2b75b500207a9c14f823d1d50f56b2aec..66078dad7fe8c353bd4de83115dc4eee73ba978f 100644 (file)
@@ -120,7 +120,7 @@ static void mroute_clean_tables(struct mr6_table *mrt);
 static void ipmr_expire_process(unsigned long arg);
 
 #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
-#define ip6mr_for_each_table(mrt, met) \
+#define ip6mr_for_each_table(mrt, net) \
        list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
 
 static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
@@ -254,8 +254,10 @@ static void __net_exit ip6mr_rules_exit(struct net *net)
 {
        struct mr6_table *mrt, *next;
 
-       list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list)
+       list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
+               list_del(&mrt->list);
                ip6mr_free_table(mrt);
+       }
        fib_rules_unregister(net->ipv6.mr6_rules_ops);
 }
 #else
index 59f1881968c70aad15b0296cf6400c6b0b3e49cb..ab1622d7d409f0a853a956ee06db49aad930050a 100644 (file)
@@ -1356,7 +1356,10 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
                     IPV6_TLV_PADN, 0 };
 
        /* we assume size > sizeof(ra) here */
-       skb = sock_alloc_send_skb(sk, size + LL_ALLOCATED_SPACE(dev), 1, &err);
+       size += LL_ALLOCATED_SPACE(dev);
+       /* limit our allocations to order-0 page */
+       size = min_t(int, size, SKB_MAX_ORDER(0, 0));
+       skb = sock_alloc_send_skb(sk, size, 1, &err);
 
        if (!skb)
                return NULL;
index 0abdc242ddb76029cc2f6a52bed1bbdea2189364..2efef52fb4616fb5d598026a35ecf1d76aba0fd8 100644 (file)
@@ -586,6 +586,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
                src_addr = solicited_addr;
                if (ifp->flags & IFA_F_OPTIMISTIC)
                        override = 0;
+               inc_opt |= ifp->idev->cnf.force_tllao;
                in6_ifa_put(ifp);
        } else {
                if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr,
@@ -599,7 +600,6 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
        icmp6h.icmp6_solicited = solicited;
        icmp6h.icmp6_override = override;
 
-       inc_opt |= ifp->idev->cnf.force_tllao;
        __ndisc_send(dev, neigh, daddr, src_addr,
                     &icmp6h, solicited_addr,
                     inc_opt ? ND_OPT_TARGET_LL_ADDR : 0);
index 6f517bd8369254ae73d0ac9888792326dd610352..9d2d68f0e6053d97fdfc3f350135604309a35808 100644 (file)
@@ -363,7 +363,7 @@ ip6t_do_table(struct sk_buff *skb,
        cpu        = smp_processor_id();
        table_base = private->entries[cpu];
        jumpstack  = (struct ip6t_entry **)private->jumpstack[cpu];
-       stackptr   = &private->stackptr[cpu];
+       stackptr   = per_cpu_ptr(private->stackptr, cpu);
        origptr    = *stackptr;
 
        e = get_entry(table_base, private->hook_entry[hook]);
index 294cbe8b0725f7ad9f58690f2b511829d391a672..252d76199c41e7589b85416bef1145e407239126 100644 (file)
@@ -814,7 +814,7 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk,
 {
        int flags = 0;
 
-       if (fl->oif || rt6_need_strict(&fl->fl6_dst))
+       if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl->fl6_dst))
                flags |= RT6_LOOKUP_F_IFACE;
 
        if (!ipv6_addr_any(&fl->fl6_src))
index c163d0a149f49be05b07fa879562f2d821004beb..98258b7341e356111bef3674f56b3a6adeee5961 100644 (file)
@@ -332,14 +332,16 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
                IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
 
        spin_unlock(&local->ampdu_lock);
-       spin_unlock_bh(&sta->lock);
 
-       /* send an addBA request */
+       /* prepare tid data */
        sta->ampdu_mlme.dialog_token_allocator++;
        sta->ampdu_mlme.tid_tx[tid]->dialog_token =
                        sta->ampdu_mlme.dialog_token_allocator;
        sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
 
+       spin_unlock_bh(&sta->lock);
+
+       /* send AddBA request */
        ieee80211_send_addba_request(sdata, pubsta->addr, tid,
                         sta->ampdu_mlme.tid_tx[tid]->dialog_token,
                         sta->ampdu_mlme.tid_tx[tid]->ssn,
index 5d218c530a4efae71826f33ac3b7868d741dd897..32be11e4c4d92dbe9d34d8cae84d7e0a482e8882 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/nl80211.h>
 #include "ieee80211_i.h"
 
-enum ieee80211_chan_mode
+static enum ieee80211_chan_mode
 __ieee80211_get_channel_mode(struct ieee80211_local *local,
                             struct ieee80211_sub_if_data *ignore)
 {
index 4f2271316650d98f08de2f1c460b4b8fb283d752..9c1da0809160215c4178358f8f17be8c6d774e27 100644 (file)
@@ -349,7 +349,7 @@ static inline int drv_get_survey(struct ieee80211_local *local, int idx,
                                struct survey_info *survey)
 {
        int ret = -EOPNOTSUPP;
-       if (local->ops->conf_tx)
+       if (local->ops->get_survey)
                ret = local->ops->get_survey(&local->hw, idx, survey);
        /* trace_drv_get_survey(local, idx, survey, ret); */
        return ret;
index 0839c4e8fd2e35b2042e968a9eddebb1e49dc99e..f803f8b72a930dd58b60ae362ea1b7117f1247b2 100644 (file)
@@ -1692,14 +1692,52 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                        rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
                        break;
                case IEEE80211_STYPE_ACTION:
-                       if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
+                       switch (mgmt->u.action.category) {
+                       case WLAN_CATEGORY_BACK: {
+                               struct ieee80211_local *local = sdata->local;
+                               int len = skb->len;
+                               struct sta_info *sta;
+
+                               rcu_read_lock();
+                               sta = sta_info_get(sdata, mgmt->sa);
+                               if (!sta) {
+                                       rcu_read_unlock();
+                                       break;
+                               }
+
+                               local_bh_disable();
+
+                               switch (mgmt->u.action.u.addba_req.action_code) {
+                               case WLAN_ACTION_ADDBA_REQ:
+                                       if (len < (IEEE80211_MIN_ACTION_SIZE +
+                                                  sizeof(mgmt->u.action.u.addba_req)))
+                                               break;
+                                       ieee80211_process_addba_request(local, sta, mgmt, len);
+                                       break;
+                               case WLAN_ACTION_ADDBA_RESP:
+                                       if (len < (IEEE80211_MIN_ACTION_SIZE +
+                                                  sizeof(mgmt->u.action.u.addba_resp)))
+                                               break;
+                                       ieee80211_process_addba_resp(local, sta, mgmt, len);
+                                       break;
+                               case WLAN_ACTION_DELBA:
+                                       if (len < (IEEE80211_MIN_ACTION_SIZE +
+                                                  sizeof(mgmt->u.action.u.delba)))
+                                               break;
+                                       ieee80211_process_delba(sdata, sta, mgmt, len);
+                                       break;
+                               }
+                               local_bh_enable();
+                               rcu_read_unlock();
                                break;
-
-                       ieee80211_sta_process_chanswitch(sdata,
-                                       &mgmt->u.action.u.chan_switch.sw_elem,
-                                       (void *)ifmgd->associated->priv,
-                                       rx_status->mactime);
-                       break;
+                               }
+                       case WLAN_CATEGORY_SPECTRUM_MGMT:
+                               ieee80211_sta_process_chanswitch(sdata,
+                                               &mgmt->u.action.u.chan_switch.sw_elem,
+                                               (void *)ifmgd->associated->priv,
+                                               rx_status->mactime);
+                               break;
+                       }
                }
                mutex_unlock(&ifmgd->mtx);
 
@@ -1722,9 +1760,45 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
        mutex_unlock(&ifmgd->mtx);
 
        if (skb->len >= 24 + 2 /* mgmt + deauth reason */ &&
-           (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH)
-               cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
+           (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) {
+               struct ieee80211_local *local = sdata->local;
+               struct ieee80211_work *wk;
+
+               mutex_lock(&local->work_mtx);
+               list_for_each_entry(wk, &local->work_list, list) {
+                       if (wk->sdata != sdata)
+                               continue;
+
+                       if (wk->type != IEEE80211_WORK_ASSOC)
+                               continue;
+
+                       if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN))
+                               continue;
+                       if (memcmp(mgmt->sa, wk->filter_ta, ETH_ALEN))
+                               continue;
 
+                       /*
+                        * Printing the message only here means we can't
+                        * spuriously print it, but it also means that it
+                        * won't be printed when the frame comes in before
+                        * we even tried to associate or in similar cases.
+                        *
+                        * Ultimately, I suspect cfg80211 should print the
+                        * messages instead.
+                        */
+                       printk(KERN_DEBUG
+                              "%s: deauthenticated from %pM (Reason: %u)\n",
+                              sdata->name, mgmt->bssid,
+                              le16_to_cpu(mgmt->u.deauth.reason_code));
+
+                       list_del_rcu(&wk->list);
+                       free_work(wk);
+                       break;
+               }
+               mutex_unlock(&local->work_mtx);
+
+               cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
+       }
  out:
        kfree_skb(skb);
 }
index 6e2a7bcd8cb888ce24be03cc56cb2516ca95fade..be9abc2e6348943753aab8daae864b561adce82f 100644 (file)
@@ -1818,17 +1818,26 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
                return RX_CONTINUE;
 
        if (ieee80211_is_back_req(bar->frame_control)) {
+               struct {
+                       __le16 control, start_seq_num;
+               } __packed bar_data;
+
                if (!rx->sta)
                        return RX_DROP_MONITOR;
+
+               if (skb_copy_bits(skb, offsetof(struct ieee80211_bar, control),
+                                 &bar_data, sizeof(bar_data)))
+                       return RX_DROP_MONITOR;
+
                spin_lock(&rx->sta->lock);
-               tid = le16_to_cpu(bar->control) >> 12;
+               tid = le16_to_cpu(bar_data.control) >> 12;
                if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) {
                        spin_unlock(&rx->sta->lock);
                        return RX_DROP_MONITOR;
                }
                tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
 
-               start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
+               start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4;
 
                /* reset session timer */
                if (tid_agg_rx->timeout)
@@ -1935,6 +1944,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                if (len < IEEE80211_MIN_ACTION_SIZE + 1)
                        break;
 
+               if (sdata->vif.type == NL80211_IFTYPE_STATION)
+                       return ieee80211_sta_rx_mgmt(sdata, rx->skb);
+
                switch (mgmt->u.action.u.addba_req.action_code) {
                case WLAN_ACTION_ADDBA_REQ:
                        if (len < (IEEE80211_MIN_ACTION_SIZE +
index be3d4a698692d1ce958b695c1e1676297b1d15cd..b025dc7bb0fd4e1decb356709cb3ac5d3163db58 100644 (file)
@@ -715,7 +715,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
        struct ieee80211_rx_status *rx_status;
        struct ieee80211_mgmt *mgmt;
        struct ieee80211_work *wk;
-       enum work_action rma;
+       enum work_action rma = WORK_ACT_NONE;
        u16 fc;
 
        rx_status = (struct ieee80211_rx_status *) skb->cb;
index d8f7e8ef67b41e2bedb7b47cf81070d9cd5cb390..ff04e9edbed6636198b294796654c5aab64d9fdd 100644 (file)
@@ -162,6 +162,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
        hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
 
        ct_write_lock(hash);
+       spin_lock(&cp->lock);
 
        if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
                list_add(&cp->c_list, &ip_vs_conn_tab[hash]);
@@ -174,6 +175,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
                ret = 0;
        }
 
+       spin_unlock(&cp->lock);
        ct_write_unlock(hash);
 
        return ret;
@@ -193,6 +195,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
        hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
 
        ct_write_lock(hash);
+       spin_lock(&cp->lock);
 
        if (cp->flags & IP_VS_CONN_F_HASHED) {
                list_del(&cp->c_list);
@@ -202,6 +205,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
        } else
                ret = 0;
 
+       spin_unlock(&cp->lock);
        ct_write_unlock(hash);
 
        return ret;
index 445de702b8b75a2dad66d96cf757a9f392ed7d80..e34622fa000357c5e24eeddd2aad835d616fd8ce 100644 (file)
@@ -699,10 +699,8 @@ void xt_free_table_info(struct xt_table_info *info)
                vfree(info->jumpstack);
        else
                kfree(info->jumpstack);
-       if (sizeof(unsigned int) * nr_cpu_ids > PAGE_SIZE)
-               vfree(info->stackptr);
-       else
-               kfree(info->stackptr);
+
+       free_percpu(info->stackptr);
 
        kfree(info);
 }
@@ -753,14 +751,9 @@ static int xt_jumpstack_alloc(struct xt_table_info *i)
        unsigned int size;
        int cpu;
 
-       size = sizeof(unsigned int) * nr_cpu_ids;
-       if (size > PAGE_SIZE)
-               i->stackptr = vmalloc(size);
-       else
-               i->stackptr = kmalloc(size, GFP_KERNEL);
+       i->stackptr = alloc_percpu(unsigned int);
        if (i->stackptr == NULL)
                return -ENOMEM;
-       memset(i->stackptr, 0, size);
 
        size = sizeof(void **) * nr_cpu_ids;
        if (size > PAGE_SIZE)
@@ -844,10 +837,6 @@ struct xt_table *xt_register_table(struct net *net,
        struct xt_table_info *private;
        struct xt_table *t, *table;
 
-       ret = xt_jumpstack_alloc(newinfo);
-       if (ret < 0)
-               return ERR_PTR(ret);
-
        /* Don't add one object to multiple lists. */
        table = kmemdup(input_table, sizeof(struct xt_table), GFP_KERNEL);
        if (!table) {
index 7b048a35ca5837368e4ace101a57564eacbb51fc..94d72e85a475ae094d14f8df5f4f54a936f0db15 100644 (file)
@@ -1045,12 +1045,12 @@ static void pep_sock_unhash(struct sock *sk)
        lock_sock(sk);
        if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) {
                skparent = pn->listener;
-               sk_del_node_init(sk);
                release_sock(sk);
 
-               sk = skparent;
                pn = pep_sk(skparent);
-               lock_sock(sk);
+               lock_sock(skparent);
+               sk_del_node_init(sk);
+               sk = skparent;
        }
        /* Unhash a listening sock only when it is closed
         * and all of its active connected pipes are closed. */
index 10ed0d55f75948702837e2154327876a521d3d8b..f68832798db224d6abffcc08f4ad494fa2b3bc17 100644 (file)
@@ -475,6 +475,7 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
        err = rds_ib_setup_qp(conn);
        if (err) {
                rds_ib_conn_error(conn, "rds_ib_setup_qp failed (%d)\n", err);
+               mutex_unlock(&conn->c_cm_lock);
                goto out;
        }
 
index a9d951b4fbaec49dfea00dc6494639b0d32403ac..b5dd6ac39be86b87afc1bd7761971a11550e572f 100644 (file)
@@ -452,6 +452,7 @@ int rds_iw_cm_handle_connect(struct rdma_cm_id *cm_id,
        err = rds_iw_setup_qp(conn);
        if (err) {
                rds_iw_conn_error(conn, "rds_iw_setup_qp failed (%d)\n", err);
+               mutex_unlock(&conn->c_cm_lock);
                goto out;
        }
 
index d885ba311564d9a766fce6eac37edbaf0ed82b71..570949417f388735e93bf887294326a8f24aa534 100644 (file)
@@ -159,6 +159,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
                        iph->daddr = new_addr;
 
                csum_replace4(&iph->check, addr, new_addr);
+       } else if ((iph->frag_off & htons(IP_OFFSET)) ||
+                  iph->protocol != IPPROTO_ICMP) {
+               goto out;
        }
 
        ihl = iph->ihl * 4;
@@ -247,6 +250,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
                break;
        }
 
+out:
        return action;
 
 drop:
index fdbd0b7bd840715c41626abfa74831ddcd9ef2fb..50e3d945e1f48a12b8a499aeb07d50f3d286017a 100644 (file)
@@ -125,7 +125,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
 {
        struct tcf_pedit *p = a->priv;
        int i, munged = 0;
-       u8 *pptr;
+       unsigned int off;
 
        if (!(skb->tc_verd & TC_OK2MUNGE)) {
                /* should we set skb->cloned? */
@@ -134,7 +134,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
                }
        }
 
-       pptr = skb_network_header(skb);
+       off = skb_network_offset(skb);
 
        spin_lock(&p->tcf_lock);
 
@@ -144,17 +144,17 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
                struct tc_pedit_key *tkey = p->tcfp_keys;
 
                for (i = p->tcfp_nkeys; i > 0; i--, tkey++) {
-                       u32 *ptr;
+                       u32 *ptr, _data;
                        int offset = tkey->off;
 
                        if (tkey->offmask) {
-                               if (skb->len > tkey->at) {
-                                        char *j = pptr + tkey->at;
-                                        offset += ((*j & tkey->offmask) >>
-                                                  tkey->shift);
-                               } else {
+                               char *d, _d;
+
+                               d = skb_header_pointer(skb, off + tkey->at, 1,
+                                                      &_d);
+                               if (!d)
                                        goto bad;
-                               }
+                               offset += (*d & tkey->offmask) >> tkey->shift;
                        }
 
                        if (offset % 4) {
@@ -169,9 +169,13 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
                                goto bad;
                        }
 
-                       ptr = (u32 *)(pptr+offset);
+                       ptr = skb_header_pointer(skb, off + offset, 4, &_data);
+                       if (!ptr)
+                               goto bad;
                        /* just do it, baby */
                        *ptr = ((*ptr & tkey->mask) ^ tkey->val);
+                       if (ptr == &_data)
+                               skb_store_bits(skb, off + offset, ptr, 4);
                        munged++;
                }
 
index 96275422c619e9d2a4e5eecd4fa8b433a526c8ab..4f522143811e467fe70e7e4b13db47f979b11b8a 100644 (file)
@@ -98,11 +98,11 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re
 {
        struct {
                struct tc_u_knode *knode;
-               u8                *ptr;
+               unsigned int      off;
        } stack[TC_U32_MAXDEPTH];
 
        struct tc_u_hnode *ht = (struct tc_u_hnode*)tp->root;
-       u8 *ptr = skb_network_header(skb);
+       unsigned int off = skb_network_offset(skb);
        struct tc_u_knode *n;
        int sdepth = 0;
        int off2 = 0;
@@ -134,8 +134,14 @@ next_knode:
 #endif
 
                for (i = n->sel.nkeys; i>0; i--, key++) {
-
-                       if ((*(__be32*)(ptr+key->off+(off2&key->offmask))^key->val)&key->mask) {
+                       unsigned int toff;
+                       __be32 *data, _data;
+
+                       toff = off + key->off + (off2 & key->offmask);
+                       data = skb_header_pointer(skb, toff, 4, &_data);
+                       if (!data)
+                               goto out;
+                       if ((*data ^ key->val) & key->mask) {
                                n = n->next;
                                goto next_knode;
                        }
@@ -174,29 +180,45 @@ check_terminal:
                if (sdepth >= TC_U32_MAXDEPTH)
                        goto deadloop;
                stack[sdepth].knode = n;
-               stack[sdepth].ptr = ptr;
+               stack[sdepth].off = off;
                sdepth++;
 
                ht = n->ht_down;
                sel = 0;
-               if (ht->divisor)
-                       sel = ht->divisor&u32_hash_fold(*(__be32*)(ptr+n->sel.hoff), &n->sel,n->fshift);
-
+               if (ht->divisor) {
+                       __be32 *data, _data;
+
+                       data = skb_header_pointer(skb, off + n->sel.hoff, 4,
+                                                 &_data);
+                       if (!data)
+                               goto out;
+                       sel = ht->divisor & u32_hash_fold(*data, &n->sel,
+                                                         n->fshift);
+               }
                if (!(n->sel.flags&(TC_U32_VAROFFSET|TC_U32_OFFSET|TC_U32_EAT)))
                        goto next_ht;
 
                if (n->sel.flags&(TC_U32_OFFSET|TC_U32_VAROFFSET)) {
                        off2 = n->sel.off + 3;
-                       if (n->sel.flags&TC_U32_VAROFFSET)
-                               off2 += ntohs(n->sel.offmask & *(__be16*)(ptr+n->sel.offoff)) >>n->sel.offshift;
+                       if (n->sel.flags & TC_U32_VAROFFSET) {
+                               __be16 *data, _data;
+
+                               data = skb_header_pointer(skb,
+                                                         off + n->sel.offoff,
+                                                         2, &_data);
+                               if (!data)
+                                       goto out;
+                               off2 += ntohs(n->sel.offmask & *data) >>
+                                       n->sel.offshift;
+                       }
                        off2 &= ~3;
                }
                if (n->sel.flags&TC_U32_EAT) {
-                       ptr += off2;
+                       off += off2;
                        off2 = 0;
                }
 
-               if (ptr < skb_tail_pointer(skb))
+               if (off < skb->len)
                        goto next_ht;
        }
 
@@ -204,9 +226,10 @@ check_terminal:
        if (sdepth--) {
                n = stack[sdepth].knode;
                ht = n->ht_up;
-               ptr = stack[sdepth].ptr;
+               off = stack[sdepth].off;
                goto check_terminal;
        }
+out:
        return -1;
 
 deadloop:
index 3415b6ce1c0a5b1116a4e23cc710c0b8f5b0f8d5..807643bdcbac30817edecfb4185dd45826b750eb 100644 (file)
@@ -449,6 +449,7 @@ static __init void teql_master_setup(struct net_device *dev)
        dev->tx_queue_len       = 100;
        dev->flags              = IFF_NOARP;
        dev->hard_header_len    = LL_MAX_HEADER;
+       dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
 }
 
 static LIST_HEAD(master_dev_list);
index 2a9675136c68e487adcf02849c54680ed7fd0e98..7ca65c7005ea5d2445ddddd617017ab3e6539f29 100644 (file)
@@ -210,7 +210,8 @@ struct sock_xprt {
         * State of TCP reply receive
         */
        __be32                  tcp_fraghdr,
-                               tcp_xid;
+                               tcp_xid,
+                               tcp_calldir;
 
        u32                     tcp_offset,
                                tcp_reclen;
@@ -927,7 +928,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
 {
        size_t len, used;
        u32 offset;
-       __be32  calldir;
+       char *p;
 
        /*
         * We want transport->tcp_offset to be 8 at the end of this routine
@@ -936,26 +937,33 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
         * transport->tcp_offset is 4 (after having already read the xid).
         */
        offset = transport->tcp_offset - sizeof(transport->tcp_xid);
-       len = sizeof(calldir) - offset;
+       len = sizeof(transport->tcp_calldir) - offset;
        dprintk("RPC:       reading CALL/REPLY flag (%Zu bytes)\n", len);
-       used = xdr_skb_read_bits(desc, &calldir, len);
+       p = ((char *) &transport->tcp_calldir) + offset;
+       used = xdr_skb_read_bits(desc, p, len);
        transport->tcp_offset += used;
        if (used != len)
                return;
        transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR;
-       transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
-       transport->tcp_flags |= TCP_RCV_COPY_DATA;
        /*
         * We don't yet have the XDR buffer, so we will write the calldir
         * out after we get the buffer from the 'struct rpc_rqst'
         */
-       if (ntohl(calldir) == RPC_REPLY)
+       switch (ntohl(transport->tcp_calldir)) {
+       case RPC_REPLY:
+               transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
+               transport->tcp_flags |= TCP_RCV_COPY_DATA;
                transport->tcp_flags |= TCP_RPC_REPLY;
-       else
+               break;
+       case RPC_CALL:
+               transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
+               transport->tcp_flags |= TCP_RCV_COPY_DATA;
                transport->tcp_flags &= ~TCP_RPC_REPLY;
-       dprintk("RPC:       reading %s CALL/REPLY flag %08x\n",
-                       (transport->tcp_flags & TCP_RPC_REPLY) ?
-                               "reply for" : "request with", calldir);
+               break;
+       default:
+               dprintk("RPC:       invalid request message type\n");
+               xprt_force_disconnect(&transport->xprt);
+       }
        xs_tcp_check_fraghdr(transport);
 }
 
@@ -975,12 +983,10 @@ static inline void xs_tcp_read_common(struct rpc_xprt *xprt,
                /*
                 * Save the RPC direction in the XDR buffer
                 */
-               __be32  calldir = transport->tcp_flags & TCP_RPC_REPLY ?
-                                       htonl(RPC_REPLY) : 0;
-
                memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied,
-                       &calldir, sizeof(calldir));
-               transport->tcp_copied += sizeof(calldir);
+                       &transport->tcp_calldir,
+                       sizeof(transport->tcp_calldir));
+               transport->tcp_copied += sizeof(transport->tcp_calldir);
                transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
        }
 
index 6a329158bdfaa14de3891194e0c98ae70f4f1834..a3cca0a94346319dec462ef7ef2fb7df2265945e 100644 (file)
@@ -95,13 +95,13 @@ resume:
                        goto error_nolock;
                }
 
-               dst = dst_pop(dst);
+               dst = skb_dst_pop(skb);
                if (!dst) {
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR);
                        err = -EHOSTUNREACH;
                        goto error_nolock;
                }
-               skb_dst_set(skb, dst);
+               skb_dst_set_noref(skb, dst);
                x = dst->xfrm;
        } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
 
index d965a2bad8d3b9cf993f72eaa372fb791642f3bc..af1c173be4ad88906d55d7efa24fb47fcd0cf19d 100644 (file)
@@ -2153,6 +2153,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
                return 0;
        }
 
+       skb_dst_force(skb);
        dst = skb_dst(skb);
 
        res = xfrm_lookup(net, &dst, &fl, NULL, 0) == 0;
@@ -2299,7 +2300,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
                        return 0;
                if (xdst->xfrm_genid != dst->xfrm->genid)
                        return 0;
-               if (xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
+               if (xdst->num_pols > 0 &&
+                   xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
                        return 0;
 
                if (strict && fl &&
index 0b94d2fa3a883ce4cf1b9bdd6219e30bc338f480..e4deb73e9a84971d46ac3dab9bd96cf8ffc8236f 100644 (file)
@@ -82,7 +82,7 @@ ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
 lib-target := $(obj)/lib.a
 endif
 
-ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),)
+ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(subdir-m) $(lib-target)),)
 builtin-target := $(obj)/built-in.o
 endif
 
index cbcd654215e68c2c0cc111737c94ae00074b9f3a..54fd1b700131e1e1fcb0ddd13d89ee3a06983ecb 100644 (file)
@@ -241,7 +241,7 @@ cmd_lzma = (cat $(filter-out FORCE,$^) | \
        lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
        (rm -f $@ ; false)
 
-quiet_cmd_lzo = LZO    $@
+quiet_cmd_lzo = LZO     $@
 cmd_lzo = (cat $(filter-out FORCE,$^) | \
        lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
        (rm -f $@ ; false)
index 102a276f6eeac9c4a1f71da4235b4e1496242659..1adb974e6950efb80943f82b1c4ca416b09b5417 100644 (file)
@@ -14,6 +14,11 @@ __modbuiltin:
 
 include scripts/Kbuild.include
 
+ifneq ($(KBUILD_SRC),)
+# Create output directory if not already present
+_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
+endif
+
 # The filename Kbuild has precedence over Makefile
 kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
 kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
index 676ddc07d6fa76b1a79603cf3be95a26eb7b7ec1..97b2c6143fe4f9d61cbc181b316e812e82dc456e 100755 (executable)
@@ -11,6 +11,8 @@
 # you do have real dups and do not have them under #ifdef's. You
 # could also just review the results.
 
+use strict;
+
 sub usage {
        print "Usage: checkincludes.pl [-r]\n";
        print "By default we just warn of duplicates\n";
@@ -35,23 +37,24 @@ if ($#ARGV >= 1) {
        }
 }
 
-foreach $file (@ARGV) {
-       open(FILE, $file) or die "Cannot open $file: $!.\n";
+foreach my $file (@ARGV) {
+       open(my $f, '<', $file)
+           or die "Cannot open $file: $!.\n";
 
        my %includedfiles = ();
        my @file_lines = ();
 
-       while (<FILE>) {
+       while (<$f>) {
                if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) {
                        ++$includedfiles{$1};
                }
                push(@file_lines, $_);
        }
 
-       close(FILE);
+       close($f);
 
        if (!$remove) {
-               foreach $filename (keys %includedfiles) {
+               foreach my $filename (keys %includedfiles) {
                        if ($includedfiles{$filename} > 1) {
                                print "$file: $filename is included more than once.\n";
                        }
@@ -59,27 +62,28 @@ foreach $file (@ARGV) {
                next;
        }
 
-       open(FILE,">$file") || die("Cannot write to $file: $!");
+       open($f, '>', $file)
+           or die("Cannot write to $file: $!");
 
        my $dups = 0;
        foreach (@file_lines) {
                if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) {
-                       foreach $filename (keys %includedfiles) {
+                       foreach my $filename (keys %includedfiles) {
                                if ($1 eq $filename) {
                                        if ($includedfiles{$filename} > 1) {
                                                $includedfiles{$filename}--;
                                                $dups++;
                                        } else {
-                                               print FILE $_;
+                                               print {$f} $_;
                                        }
                                }
                        }
                } else {
-                       print FILE $_;
+                       print {$f} $_;
                }
        }
        if ($dups > 0) {
                print "$file: removed $dups duplicate includes\n";
        }
-       close(FILE);
+       close($f);
 }
index 14ee68e991dd45767b8ded17747da02a59c703f1..1afff6658a7d2a657333ff8815486b998b5c16bd 100755 (executable)
@@ -21,6 +21,8 @@
 #
 #      TODO :  Port to all architectures (one regex per arch)
 
+use strict;
+
 # check for arch
 #
 # $re is used for two matches:
@@ -104,19 +106,11 @@ my (@stack, $re, $dre, $x, $xs);
        }
 }
 
-sub bysize($) {
-       my ($asize, $bsize);
-       ($asize = $a) =~ s/.*:  *(.*)$/$1/;
-       ($bsize = $b) =~ s/.*:  *(.*)$/$1/;
-       $bsize <=> $asize
-}
-
 #
 # main()
 #
 my $funcre = qr/^$x* <(.*)>:$/;
-my $func;
-my $file, $lastslash;
+my ($func, $file, $lastslash);
 
 while (my $line = <STDIN>) {
        if ($line =~ m/$funcre/) {
@@ -173,4 +167,6 @@ while (my $line = <STDIN>) {
        }
 }
 
-print sort bysize @stack;
+# Sort output by size (last field)
+print sort { ($b =~ /:\t*(\d+)$/)[0] <=> ($a =~ /:\t*(\d+)$/)[0] } @stack;
+
index ec7d21161bdcb873ee38926c4097a23b44702880..b444e89a0095dc16d207fb23a7600a148c67834b 100755 (executable)
@@ -5,23 +5,22 @@
 # including <linux/version.h> that don't need it.
 # Copyright (C) 2003, Randy Dunlap <rdunlap@xenotime.net>
 
+use strict;
+
 $| = 1;
 
-my $debugging = 0;
+my $debugging;
 
-foreach $file (@ARGV)
-{
+foreach my $file (@ARGV) {
     # Open this file.
-    open(FILE, $file) || die "Can't open $file: $!\n";
+    open( my $f, '<', $file )
+      or die "Can't open $file: $!\n";
 
     # Initialize variables.
-    my $fInComment   = 0;
-    my $fInString    = 0;
-    my $fUseVersion   = 0;
+    my ($fInComment, $fInString, $fUseVersion);
     my $iLinuxVersion = 0;
 
-    LINE: while ( <FILE> )
-    {
+    while (<$f>) {
        # Strip comments.
        $fInComment && (s+^.*?\*/+ +o ? ($fInComment = 0) : next);
        m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1)));
@@ -43,8 +42,8 @@ foreach $file (@ARGV)
        # Look for uses: LINUX_VERSION_CODE, KERNEL_VERSION, UTS_RELEASE
        if (($_ =~ /LINUX_VERSION_CODE/) || ($_ =~ /\WKERNEL_VERSION/)) {
            $fUseVersion = 1;
-           last LINE if $iLinuxVersion;
-       }
+            last if $iLinuxVersion;
+        }
     }
 
     # Report used version IDs without include?
@@ -67,5 +66,5 @@ foreach $file (@ARGV)
         }
     }
 
-    close(FILE);
+    close($f);
 }
index 4b00647814bc46c9525dfc6e806d28af7641f9d6..8b30cc36744f8c2c1d5c24fcaebc9d2cfbd1889e 100755 (executable)
@@ -7,7 +7,7 @@
 # AFLAGS=--32 decodecode < 386.oops
 
 cleanup() {
-       rm -f $T $T.s $T.o $T.oo $T.aa  $T.aaa
+       rm -f $T $T.s $T.o $T.oo $T.aa $T.dis
        exit 1
 }
 
@@ -39,6 +39,29 @@ fi
 echo $code
 code=`echo $code | sed -e 's/.*Code: //'`
 
+width=`expr index "$code" ' '`
+width=$[($width-1)/2]
+case $width in
+1) type=byte ;;
+2) type=2byte ;;
+4) type=4byte ;;
+esac
+
+disas() {
+       ${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s &> /dev/null
+
+       if [ "$ARCH" == "arm" ]; then
+               if [ $width == 2 ]; then
+                       OBJDUMPFLAGS="-M force-thumb"
+               fi
+
+               ${CROSS_COMPILE}strip $1.o
+       fi
+
+       ${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $1.o | \
+               grep -v "/tmp\|Disassembly\|\.text\|^$" &> $1.dis
+}
+
 marker=`expr index "$code" "\<"`
 if [ $marker -eq 0 ]; then
        marker=`expr index "$code" "\("`
@@ -49,26 +72,25 @@ if [ $marker -ne 0 ]; then
        echo All code >> $T.oo
        echo ======== >> $T.oo
        beforemark=`echo "$code"`
-       echo -n "       .byte 0x" > $T.s
-       echo $beforemark | sed -e 's/ /,0x/g' | sed -e 's/<//g' | sed -e 's/>//g' >> $T.s
-       as $AFLAGS -o $T.o $T.s &> /dev/null
-       objdump -S $T.o | grep -v "/tmp" | grep -v "Disassembly" | grep -v "\.text" | grep -v "^$" &> $T.ooo
-       cat $T.ooo >> $T.oo
-       rm -f $T.o $T.s  $T.ooo
+       echo -n "       .$type 0x" > $T.s
+       echo $beforemark | sed -e 's/ /,0x/g; s/[<>()]//g' >> $T.s
+       disas $T
+       cat $T.dis >> $T.oo
+       rm -f $T.o $T.s $T.dis
 
 # and fix code at-and-after marker
        code=`echo "$code" | cut -c$((${marker} + 1))-`
 fi
 echo Code starting with the faulting instruction  > $T.aa
 echo =========================================== >> $T.aa
-code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g'`
-echo -n "      .byte 0x" > $T.s
+code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g; s/[>)]$//'`
+echo -n "      .$type 0x" > $T.s
 echo $code >> $T.s
-as $AFLAGS -o $T.o $T.s &> /dev/null
-objdump -S $T.o | grep -v "Disassembly" | grep -v "/tmp" | grep -v "\.text" | grep -v "^$" &> $T.aaa
-cat $T.aaa >> $T.aa
+disas $T
+cat $T.dis >> $T.aa
 
-faultline=`cat $T.aaa | head -1 | cut -d":" -f2`
+faultline=`cat $T.dis | head -1 | cut -d":" -f2`
+faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'`
 
 cat $T.oo | sed -e "s/\($faultline\)/\*\1     <-- trapping instruction/g"
 echo
index 705b5ba7c1526c65bbcf2d0868f2a2f007a158e9..04dce7c15f8328c71f3ce5f6bff4ef9ef0882eac 100644 (file)
@@ -49,10 +49,10 @@ sub usage {
 }
 
 sub collectcfiles {
-        my @file = `cat .tmp_versions/*.mod | grep '.*\.ko\$'`;
-        @file = grep {s/\.ko/.mod.c/} @file;
-       chomp @file;
-        return @file;
+    my @file
+       = `cat .tmp_versions/*.mod | grep '.*\.ko\$' | sed s/\.ko$/.mod.c/`;
+    chomp @file;
+    return @file;
 }
 
 my (%SYMBOL, %MODULE, %opt, @allcfiles);
@@ -71,37 +71,40 @@ if (not defined $opt{'k'}) {
        $opt{'k'} = "Module.symvers";
 }
 
-unless (open(MODULE_SYMVERS, $opt{'k'})) {
-       die "Sorry, cannot open $opt{'k'}: $!\n";
-}
+open (my $module_symvers, '<', $opt{'k'})
+    or die "Sorry, cannot open $opt{'k'}: $!\n";
 
 if (defined $opt{'o'}) {
-       unless (open(OUTPUT_HANDLE, ">$opt{'o'}")) {
-               die "Sorry, cannot open $opt{'o'} $!\n";
-       }
-       select OUTPUT_HANDLE;
+    open (my $out, '>', $opt{'o'})
+       or die "Sorry, cannot open $opt{'o'} $!\n";
+
+    select $out;
 }
+
 #
 # collect all the symbols and their attributes from the
 # Module.symvers file
 #
-while ( <MODULE_SYMVERS> ) {
+while ( <$module_symvers> ) {
        chomp;
        my (undef, $symbol, $module, $gpl) = split;
        $SYMBOL { $symbol } =  [ $module , "0" , $symbol, $gpl];
 }
-close(MODULE_SYMVERS);
+close($module_symvers);
 
 #
 # collect the usage count of each symbol.
 #
 foreach my $thismod (@allcfiles) {
-       unless (open(MODULE_MODULE, $thismod)) {
-               print "Sorry, cannot open $thismod: $!\n";
+       my $module;
+
+       unless (open ($module, '<', $thismod)) {
+               warn "Sorry, cannot open $thismod: $!\n";
                next;
        }
+
        my $state=0;
-       while ( <MODULE_MODULE> ) {
+       while ( <$module> ) {
                chomp;
                if ($state == 0) {
                        $state = 1 if ($_ =~ /static const struct modversion_info/);
@@ -124,7 +127,7 @@ foreach my $thismod (@allcfiles) {
        if ($state != 2) {
                print "WARNING:$thismod is not built with CONFIG_MODVERSION enabled\n";
        }
-       close(MODULE_MODULE);
+       close($module);
 }
 
 print "\tThis file reports the exported symbols usage patterns by in-tree\n",
index a932ae52f921b5967b705432d0ef972f60c73c24..5958fffb2114fdedfb961858b524e6b42fe8ce2b 100644 (file)
@@ -202,6 +202,7 @@ input_file() {
                        print_mtime "$1" >> ${output}
                        cat "$1"         >> ${output}
                else
+                       echo "$1 \\"
                        cat "$1" | while read type dir file perm ; do
                                if [ "$type" == "file" ]; then
                                        echo "$file \\";
@@ -231,7 +232,7 @@ arg="$1"
 case "$arg" in
        "-l")   # files included in initramfs - used by kbuild
                dep_list="list_"
-               echo "deps_initramfs := \\"
+               echo "deps_initramfs := $0 \\"
                shift
                ;;
        "-o")   # generate compressed cpio image named $1
index af6b8363a2d51ffd1a0d2b61f40f10927e78cbce..f99115ebe9254a4ef630eabe127bc7cf25e2195c 100644 (file)
@@ -758,8 +758,10 @@ int main(int argc, char **argv)
                /* setlinebuf(debugfile); */
        }
 
-       if (flag_reference)
+       if (flag_reference) {
                read_reference(ref_file);
+               fclose(ref_file);
+       }
 
        yyparse();
 
index b7f6c560e24d2e88aabb36aea8272465eb94936c..8dd019bc5a7361631c71dc1d5e33095b6f42b6a1 100755 (executable)
@@ -80,8 +80,7 @@ sub search {
                my $path = "$i/$filename";
                return $path if -f $path;
        }
-
-       return undef;
+       return;
 }
 
 sub parse_all {
index db1dd7a549f2b9e1259148c39175ad6ee6df3d02..50d6cfd1fa778808b659a461884113de502f3f99 100644 (file)
@@ -28,11 +28,12 @@ my $lineno = 0;
 my $filename;
 
 foreach my $file (@files) {
-       local *FH;
        $filename = $file;
-       open(FH, "<$filename") or die "$filename: $!\n";
+
+       open(my $fh, '<', $filename)
+               or die "$filename: $!\n";
        $lineno = 0;
-       while ($line = <FH>) {
+       while ($line = <$fh>) {
                $lineno++;
                &check_include();
                &check_asm_types();
@@ -40,7 +41,7 @@ foreach my $file (@files) {
                &check_declarations();
                # Dropped for now. Too much noise &check_config();
        }
-       close FH;
+       close $fh;
 }
 exit $ret;
 
@@ -78,7 +79,7 @@ sub check_config
 }
 
 my $linux_asm_types;
-sub check_asm_types()
+sub check_asm_types
 {
        if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
                return;
index b89ca2c58fdbbe3592f97a27592675417713653c..4ca3be3b2e50ef90c0a0e5e5e054aec081405b1b 100644 (file)
@@ -23,13 +23,13 @@ my ($readdir, $installdir, $arch, @files) = @ARGV;
 my $unifdef = "scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__";
 
 foreach my $file (@files) {
-       local *INFILE;
-       local *OUTFILE;
        my $tmpfile = "$installdir/$file.tmp";
-       open(INFILE, "<$readdir/$file")
-               or die "$readdir/$file: $!\n";
-       open(OUTFILE, ">$tmpfile") or die "$tmpfile: $!\n";
-       while (my $line = <INFILE>) {
+
+       open(my $in, '<', "$readdir/$file")
+           or die "$readdir/$file: $!\n";
+       open(my $out, '>', $tmpfile)
+           or die "$tmpfile: $!\n";
+       while (my $line = <$in>) {
                $line =~ s/([\s(])__user\s/$1/g;
                $line =~ s/([\s(])__force\s/$1/g;
                $line =~ s/([\s(])__iomem\s/$1/g;
@@ -39,10 +39,11 @@ foreach my $file (@files) {
                $line =~ s/(^|\s)(inline)\b/$1__$2__/g;
                $line =~ s/(^|\s)(asm)\b(\s|[(]|$)/$1__$2__$3/g;
                $line =~ s/(^|\s|[(])(volatile)\b(\s|[(]|$)/$1__$2__$3/g;
-               printf OUTFILE "%s", $line;
+               printf {$out} "%s", $line;
        }
-       close OUTFILE;
-       close INFILE;
+       close $out;
+       close $in;
+
        system $unifdef . " $tmpfile > $installdir/$file";
        unlink $tmpfile;
 }
index 86c3896a1e01862b222adeaac4e33bc9b8a01aad..e3902fb39afd1f2c53f63c0cfa9aaa1273956a02 100644 (file)
@@ -108,8 +108,10 @@ static int read_symbol(FILE *in, struct sym_entry *s)
        rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str);
        if (rc != 3) {
                if (rc != EOF) {
-                       /* skip line */
-                       fgets(str, 500, in);
+                       /* skip line. sym is used as dummy to
+                        * shut of "warn_unused_result" warning.
+                        */
+                       sym = fgets(str, 500, in);
                }
                return -1;
        }
index 186c46604d0669f8f1d4cfbcaf7ad0cdc6d658fa..7ea649da19400252ba751bfdb8bea5e7a5dba426 100644 (file)
@@ -23,6 +23,9 @@ menuconfig: $(obj)/mconf
 config: $(obj)/conf
        $< $(Kconfig)
 
+nconfig: $(obj)/nconf
+       $< $(Kconfig)
+
 oldconfig: $(obj)/conf
        $< -o $(Kconfig)
 
@@ -120,6 +123,7 @@ endif
 # Help text used by make help
 help:
        @echo  '  config          - Update current config utilising a line-oriented program'
+       @echo  '  nconfig         - Update current config utilising a ncurses menu based program'
        @echo  '  menuconfig      - Update current config utilising a menu based program'
        @echo  '  xconfig         - Update current config utilising a QT based front-end'
        @echo  '  gconfig         - Update current config utilising a GTK based front-end'
@@ -147,6 +151,8 @@ HOST_EXTRACFLAGS += -DLOCALE
 # ===========================================================================
 # Shared Makefile for the various kconfig executables:
 # conf:          Used for defconfig, oldconfig and related targets
+# nconf:  Used for the nconfig target.
+#         Utilizes ncurses
 # mconf:  Used for the menuconfig target
 #         Utilizes the lxdialog package
 # qconf:  Used for the xconfig target
@@ -159,11 +165,16 @@ lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o
 lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
 
 conf-objs      := conf.o  zconf.tab.o
-mconf-objs     := mconf.o zconf.tab.o $(lxdialog)
+mconf-objs     := mconf.o zconf.tab.o $(lxdialog)
+nconf-objs     := nconf.o zconf.tab.o nconf.gui.o
 kxgettext-objs := kxgettext.o zconf.tab.o
 
 hostprogs-y := conf qconf gconf kxgettext
 
+ifeq ($(MAKECMDGOALS),nconfig)
+       hostprogs-y += nconf
+endif
+
 ifeq ($(MAKECMDGOALS),menuconfig)
        hostprogs-y += mconf
 endif
@@ -187,7 +198,7 @@ endif
 
 clean-files    := lkc_defs.h qconf.moc .tmp_qtcheck \
                   .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c gconf.glade.h
-clean-files     += mconf qconf gconf
+clean-files     += mconf qconf gconf nconf
 clean-files     += config.pot linux.pot
 
 # Check that we have the required ncurses stuff installed for lxdialog (menuconfig)
@@ -208,10 +219,11 @@ HOSTCFLAGS_zconf.tab.o    := -I$(src)
 HOSTLOADLIBES_qconf    = $(KC_QT_LIBS) -ldl
 HOSTCXXFLAGS_qconf.o   = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK
 
-HOSTLOADLIBES_gconf    = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
+HOSTLOADLIBES_gconf    = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` -ldl
 HOSTCFLAGS_gconf.o     = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
                           -D LKC_DIRECT_LINK
 
+HOSTLOADLIBES_nconf    = -lmenu -lpanel -lncurses
 $(obj)/qconf.o: $(obj)/.tmp_qtcheck
 
 ifeq ($(qconf-target),1)
index edd3f39a080a422175bf512c94dd1d5bf87e059b..d83f2322893a8adb10f027e2c4fa4757a33e26f0 100644 (file)
@@ -1097,9 +1097,32 @@ void expr_fprint(struct expr *e, FILE *out)
 
 static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
 {
-       str_append((struct gstr*)data, str);
+       struct gstr *gs = (struct gstr*)data;
+       const char *sym_str = NULL;
+
+       if (sym)
+               sym_str = sym_get_string_value(sym);
+
+       if (gs->max_width) {
+               unsigned extra_length = strlen(str);
+               const char *last_cr = strrchr(gs->s, '\n');
+               unsigned last_line_length;
+
+               if (sym_str)
+                       extra_length += 4 + strlen(sym_str);
+
+               if (!last_cr)
+                       last_cr = gs->s;
+
+               last_line_length = strlen(gs->s) - (last_cr - gs->s);
+
+               if ((last_line_length + extra_length) > gs->max_width)
+                       str_append(gs, "\\\n");
+       }
+
+       str_append(gs, str);
        if (sym)
-               str_printf((struct gstr*)data, " [=%s]", sym_get_string_value(sym));
+               str_printf(gs, " [=%s]", sym_str);
 }
 
 void expr_gstr_print(struct expr *e, struct gstr *gs)
index 6408fefae083703e2fa3d8e8a3d4f8a814f44f0b..891cd9ce9ba21b915d0b0aa993fc2d0c8d2fb10c 100644 (file)
@@ -86,7 +86,7 @@ struct symbol {
        struct expr_value rev_dep;
 };
 
-#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
+#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
 
 #define SYMBOL_CONST      0x0001  /* symbol is const */
 #define SYMBOL_CHECK      0x0008  /* used during dependency checking */
@@ -108,8 +108,7 @@ struct symbol {
 #define SYMBOL_DEF4       0x80000  /* symbol.def[S_DEF_4] is valid */
 
 #define SYMBOL_MAXLENGTH       256
-#define SYMBOL_HASHSIZE                257
-#define SYMBOL_HASHMASK                0xff
+#define SYMBOL_HASHSIZE                9973
 
 /* A property represent the config options that can be associated
  * with a config "symbol".
index 65464366fe389ab67e631c64646717c67303d05b..bef10411837fb758bdf564818aa2c23888ad8958 100644 (file)
@@ -30,13 +30,16 @@ enum {
        SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
 };
 
+enum {
+       OPT_NORMAL, OPT_ALL, OPT_PROMPT
+};
+
 static gint view_mode = FULL_VIEW;
 static gboolean show_name = TRUE;
 static gboolean show_range = TRUE;
 static gboolean show_value = TRUE;
-static gboolean show_all = FALSE;
-static gboolean show_debug = FALSE;
 static gboolean resizeable = FALSE;
+static int opt_mode = OPT_NORMAL;
 
 GtkWidget *main_wnd = NULL;
 GtkWidget *tree1_w = NULL;     // left  frame
@@ -76,36 +79,7 @@ static void conf_changed(void);
 
 /* Helping/Debugging Functions */
 
-
-const char *dbg_print_stype(int val)
-{
-       static char buf[256];
-
-       bzero(buf, 256);
-
-       if (val == S_UNKNOWN)
-               strcpy(buf, "unknown");
-       if (val == S_BOOLEAN)
-               strcpy(buf, "boolean");
-       if (val == S_TRISTATE)
-               strcpy(buf, "tristate");
-       if (val == S_INT)
-               strcpy(buf, "int");
-       if (val == S_HEX)
-               strcpy(buf, "hex");
-       if (val == S_STRING)
-               strcpy(buf, "string");
-       if (val == S_OTHER)
-               strcpy(buf, "other");
-
-#ifdef DEBUG
-       printf("%s", buf);
-#endif
-
-       return buf;
-}
-
-const char *dbg_print_flags(int val)
+const char *dbg_sym_flags(int val)
 {
        static char buf[256];
 
@@ -131,40 +105,10 @@ const char *dbg_print_flags(int val)
                strcat(buf, "auto/");
 
        buf[strlen(buf) - 1] = '\0';
-#ifdef DEBUG
-       printf("%s", buf);
-#endif
-
-       return buf;
-}
-
-const char *dbg_print_ptype(int val)
-{
-       static char buf[256];
-
-       bzero(buf, 256);
-
-       if (val == P_UNKNOWN)
-               strcpy(buf, "unknown");
-       if (val == P_PROMPT)
-               strcpy(buf, "prompt");
-       if (val == P_COMMENT)
-               strcpy(buf, "comment");
-       if (val == P_MENU)
-               strcpy(buf, "menu");
-       if (val == P_DEFAULT)
-               strcpy(buf, "default");
-       if (val == P_CHOICE)
-               strcpy(buf, "choice");
-
-#ifdef DEBUG
-       printf("%s", buf);
-#endif
 
        return buf;
 }
 
-
 void replace_button_icon(GladeXML * xml, GdkDrawable * window,
                         GtkStyle * style, gchar * btn_name, gchar ** xpm)
 {
@@ -697,20 +641,29 @@ void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
 
 
 void
-on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
+on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
 {
-       show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
+       opt_mode = OPT_NORMAL;
+       gtk_tree_store_clear(tree2);
+       display_tree(&rootmenu);        /* instead of update_tree to speed-up */
+}
+
 
+void
+on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
+{
+       opt_mode = OPT_ALL;
        gtk_tree_store_clear(tree2);
-       display_tree(&rootmenu);        // instead of update_tree to speed-up
+       display_tree(&rootmenu);        /* instead of update_tree to speed-up */
 }
 
 
 void
-on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
+on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
 {
-       show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
-       update_tree(&rootmenu, NULL);
+       opt_mode = OPT_PROMPT;
+       gtk_tree_store_clear(tree2);
+       display_tree(&rootmenu);        /* instead of update_tree to speed-up */
 }
 
 
@@ -1163,7 +1116,10 @@ static gchar **fill_row(struct menu *menu)
            g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
                            sym && sym_has_value(sym) ? "(NEW)" : "");
 
-       if (show_all && !menu_is_visible(menu))
+       if (opt_mode == OPT_ALL && !menu_is_visible(menu))
+               row[COL_COLOR] = g_strdup("DarkGray");
+       else if (opt_mode == OPT_PROMPT &&
+                       menu_has_prompt(menu) && !menu_is_visible(menu))
                row[COL_COLOR] = g_strdup("DarkGray");
        else
                row[COL_COLOR] = g_strdup("Black");
@@ -1386,16 +1342,19 @@ static void update_tree(struct menu *src, GtkTreeIter * dst)
                       menu2 ? menu_get_prompt(menu2) : "nil");
 #endif
 
-               if (!menu_is_visible(child1) && !show_all) {    // remove node
+               if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
+                   (opt_mode == OPT_PROMPT && !menu_has_prompt(child1))) {
+
+                       /* remove node */
                        if (gtktree_iter_find_node(dst, menu1) != NULL) {
                                memcpy(&tmp, child2, sizeof(GtkTreeIter));
                                valid = gtk_tree_model_iter_next(model2,
                                                                 child2);
                                gtk_tree_store_remove(tree2, &tmp);
                                if (!valid)
-                                       return; // next parent
+                                       return;         /* next parent */
                                else
-                                       goto reparse;   // next child
+                                       goto reparse;   /* next child */
                        } else
                                continue;
                }
@@ -1464,17 +1423,19 @@ static void display_tree(struct menu *menu)
                    && (tree == tree2))
                        continue;
 
-               if (menu_is_visible(child) || show_all)
+               if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
+                   (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
+                   (opt_mode == OPT_ALL))
                        place_node(child, fill_row(child));
 #ifdef DEBUG
                printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
                printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
-               dbg_print_ptype(ptype);
+               printf("%s", prop_get_type_name(ptype));
                printf(" | ");
                if (sym) {
-                       dbg_print_stype(sym->type);
+                       printf("%s", sym_type_name(sym->type));
                        printf(" | ");
-                       dbg_print_flags(sym->flags);
+                       printf("%s", dbg_sym_flags(sym->flags));
                        printf("\n");
                } else
                        printf("\n");
index b1c86c19292cb01d43b8637acddcf701bf93d844..d52b0a75d8247c69a1c153b3e39072c596c551ef 100644 (file)
                  </child>
 
                  <child>
-                   <widget class="GtkCheckMenuItem" id="show_all_options1">
+                   <widget class="GtkRadioMenuItem" id="set_option_mode1">
+                     <property name="visible">True</property>
+                     <property name="tooltip" translatable="yes">Show normal options</property>
+                     <property name="label" translatable="yes">Show normal options</property>
+                     <property name="use_underline">True</property>
+                     <property name="active">True</property>
+                     <signal name="activate" handler="on_set_option_mode1_activate"/>
+                   </widget>
+                 </child>
+
+                 <child>
+                   <widget class="GtkRadioMenuItem" id="set_option_mode2">
                      <property name="visible">True</property>
                      <property name="tooltip" translatable="yes">Show all options</property>
                      <property name="label" translatable="yes">Show all _options</property>
                      <property name="use_underline">True</property>
                      <property name="active">False</property>
-                     <signal name="activate" handler="on_show_all_options1_activate"/>
+                     <property name="group">set_option_mode1</property>
+                     <signal name="activate" handler="on_set_option_mode2_activate"/>
                    </widget>
                  </child>
 
                  <child>
-                   <widget class="GtkCheckMenuItem" id="show_debug_info1">
+                   <widget class="GtkRadioMenuItem" id="set_option_mode3">
                      <property name="visible">True</property>
-                     <property name="tooltip" translatable="yes">Show masked options</property>
-                     <property name="label" translatable="yes">Show _debug info</property>
+                     <property name="tooltip" translatable="yes">Show all options with prompts</property>
+                     <property name="label" translatable="yes">Show all prompt options</property>
                      <property name="use_underline">True</property>
                      <property name="active">False</property>
-                     <signal name="activate" handler="on_show_debug_info1_activate"/>
+                     <property name="group">set_option_mode1</property>
+                     <signal name="activate" handler="on_set_option_mode3_activate"/>
                    </widget>
                  </child>
+
                </widget>
              </child>
            </widget>
index f379b0bf8c9e7b8d45a6bd9a7f689af7165fcec6..ce6549cdaccf4b79443d1e06267502f68e769d89 100644 (file)
@@ -84,7 +84,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode);
 void kconfig_load(void);
 
 /* menu.c */
-void menu_init(void);
+void _menu_init(void);
 void menu_warn(struct menu *menu, const char *fmt, ...);
 struct menu *menu_add_menu(void);
 void menu_end_menu(void);
@@ -106,6 +106,11 @@ int file_write_dep(const char *name);
 struct gstr {
        size_t len;
        char  *s;
+       /*
+       * when max_width is not zero long lines in string s (if any) get
+       * wrapped not to exceed the max_width value
+       */
+       int max_width;
 };
 struct gstr str_new(void);
 struct gstr str_assign(const char *s);
index ffeb532b2cff3a71705693f132dc5a5eb9d94bf4..7cadcad8233bb37cd8c2e40ccae7d999a1284a63 100644 (file)
@@ -11,13 +11,15 @@ P(conf_set_changed_callback, void,(void (*fn)(void)));
 /* menu.c */
 P(rootmenu,struct menu,);
 
-P(menu_is_visible,bool,(struct menu *menu));
+P(menu_is_visible, bool, (struct menu *menu));
+P(menu_has_prompt, bool, (struct menu *menu));
 P(menu_get_prompt,const char *,(struct menu *menu));
 P(menu_get_root_menu,struct menu *,(struct menu *menu));
 P(menu_get_parent_menu,struct menu *,(struct menu *menu));
 P(menu_has_help,bool,(struct menu *menu));
 P(menu_get_help,const char *,(struct menu *menu));
-P(get_symbol_str,void,(struct gstr *r, struct symbol *sym));
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym));
+P(get_relations_str, struct gstr, (struct symbol **sym_arr));
 P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
 
 /* symbol.c */
index 616c60138183c8c9b74c3f2562f7e4a1e5b6d5d9..dd8e587c50e26eada18fe35995aaa0ec301f42fc 100644 (file)
@@ -180,7 +180,7 @@ do_resize:
                case KEY_LEFT:
                        switch (button) {
                        case -1:
-                               button = 1;     /* Indicates "Cancel" button is selected */
+                               button = 1;     /* Indicates "Help" button is selected */
                                print_buttons(dialog, height, width, 1);
                                break;
                        case 0:
@@ -204,7 +204,7 @@ do_resize:
                                print_buttons(dialog, height, width, 0);
                                break;
                        case 0:
-                               button = 1;     /* Indicates "Cancel" button is selected */
+                               button = 1;     /* Indicates "Help" button is selected */
                                print_buttons(dialog, height, width, 1);
                                break;
                        case 1:
index fa9d633f293c7c3a107b956e15774afd27560b12..1d604738fa1314a3479362082208b3591385d890 100644 (file)
@@ -383,6 +383,10 @@ do_resize:
                case 'n':
                case 'm':
                case '/':
+               case 'h':
+               case '?':
+               case 'z':
+               case '\n':
                        /* save scroll info */
                        *s_scroll = scroll;
                        delwin(menu);
@@ -390,8 +394,10 @@ do_resize:
                        item_set(scroll + choice);
                        item_set_selected(1);
                        switch (key) {
+                       case 'h':
+                       case '?':
+                               return 2;
                        case 's':
-                               return 3;
                        case 'y':
                                return 3;
                        case 'n':
@@ -402,18 +408,12 @@ do_resize:
                                return 6;
                        case '/':
                                return 7;
+                       case 'z':
+                               return 8;
+                       case '\n':
+                               return button;
                        }
                        return 0;
-               case 'h':
-               case '?':
-                       button = 2;
-               case '\n':
-                       *s_scroll = scroll;
-                       delwin(menu);
-                       delwin(dialog);
-                       item_set(scroll + choice);
-                       item_set_selected(1);
-                       return button;
                case 'e':
                case 'x':
                        key = KEY_ESC;
index 8413cf38ed277ea0061efb708c9db881ab4b6a12..2c83d3234d304dc0c3d25fac44b1af59c1a631fb 100644 (file)
@@ -67,13 +67,15 @@ static const char mconf_readme[] = N_(
 "             there is a delayed response which you may find annoying.\n"
 "\n"
 "   Also, the <TAB> and cursor keys will cycle between <Select>,\n"
-"   <Exit> and <Help>\n"
+"   <Exit> and <Help>.\n"
 "\n"
 "o  To get help with an item, use the cursor keys to highlight <Help>\n"
-"   and Press <ENTER>.\n"
+"   and press <ENTER>.\n"
 "\n"
 "   Shortcut: Press <H> or <?>.\n"
 "\n"
+"o  To show hidden options, press <Z>.\n"
+"\n"
 "\n"
 "Radiolists  (Choice lists)\n"
 "-----------\n"
@@ -272,6 +274,7 @@ static int indent;
 static struct menu *current_menu;
 static int child_count;
 static int single_menu_mode;
+static int show_all_options;
 
 static void conf(struct menu *menu);
 static void conf_choice(struct menu *menu);
@@ -282,19 +285,6 @@ static void show_textbox(const char *title, const char *text, int r, int c);
 static void show_helptext(const char *title, const char *text);
 static void show_help(struct menu *menu);
 
-static struct gstr get_relations_str(struct symbol **sym_arr)
-{
-       struct symbol *sym;
-       struct gstr res = str_new();
-       int i;
-
-       for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
-               get_symbol_str(&res, sym);
-       if (!i)
-               str_append(&res, _("No matches found.\n"));
-       return res;
-}
-
 static char filename[PATH_MAX+1];
 static void set_config_filename(const char *config_filename)
 {
@@ -359,8 +349,16 @@ static void build_conf(struct menu *menu)
        int type, tmp, doint = 2;
        tristate val;
        char ch;
-
-       if (!menu_is_visible(menu))
+       bool visible;
+
+       /*
+        * note: menu_is_visible() has side effect that it will
+        * recalc the value of the symbol.
+        */
+       visible = menu_is_visible(menu);
+       if (show_all_options && !menu_has_prompt(menu))
+               return;
+       else if (!show_all_options && !visible)
                return;
 
        sym = menu->sym;
@@ -619,6 +617,9 @@ static void conf(struct menu *menu)
                case 7:
                        search_conf();
                        break;
+               case 8:
+                       show_all_options = !show_all_options;
+                       break;
                }
        }
 }
@@ -638,6 +639,7 @@ static void show_help(struct menu *menu)
 {
        struct gstr help = str_new();
 
+       help.max_width = getmaxx(stdscr) - 10;
        menu_get_ext_help(menu, &help);
 
        show_helptext(_(menu_get_prompt(menu)), str_get(&help));
index 059a2465c5744ffed6d3cff25e2d8135a16c0399..203632cc30bdbe12ad0644c3aff15ed07a4e7c0d 100644 (file)
@@ -38,7 +38,7 @@ static void prop_warn(struct property *prop, const char *fmt, ...)
        va_end(ap);
 }
 
-void menu_init(void)
+void _menu_init(void)
 {
        current_entry = current_menu = &rootmenu;
        last_entry_ptr = &rootmenu.list;
@@ -197,7 +197,7 @@ static void sym_check_prop(struct symbol *sym)
                        if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
                            prop->expr->type != E_SYMBOL)
                                prop_warn(prop,
-                                   "default for config symbol '%'"
+                                   "default for config symbol '%s'"
                                    " must be a single symbol", sym->name);
                        break;
                case P_SELECT:
@@ -390,6 +390,13 @@ void menu_finalize(struct menu *parent)
        }
 }
 
+bool menu_has_prompt(struct menu *menu)
+{
+       if (!menu->prompt)
+               return false;
+       return true;
+}
+
 bool menu_is_visible(struct menu *menu)
 {
        struct menu *child;
@@ -398,6 +405,7 @@ bool menu_is_visible(struct menu *menu)
 
        if (!menu->prompt)
                return false;
+
        sym = menu->sym;
        if (sym) {
                sym_calc_value(sym);
@@ -407,12 +415,14 @@ bool menu_is_visible(struct menu *menu)
 
        if (visible != no)
                return true;
+
        if (!sym || sym_get_tristate_value(menu->sym) == no)
                return false;
 
        for (child = menu->list; child; child = child->next)
                if (menu_is_visible(child))
                        return true;
+
        return false;
 }
 
@@ -515,6 +525,20 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
        str_append(r, "\n\n");
 }
 
+struct gstr get_relations_str(struct symbol **sym_arr)
+{
+       struct symbol *sym;
+       struct gstr res = str_new();
+       int i;
+
+       for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
+               get_symbol_str(&res, sym);
+       if (!i)
+               str_append(&res, _("No matches found.\n"));
+       return res;
+}
+
+
 void menu_get_ext_help(struct menu *menu, struct gstr *help)
 {
        struct symbol *sym = menu->sym;
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
new file mode 100644 (file)
index 0000000..762caf8
--- /dev/null
@@ -0,0 +1,1568 @@
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+#include "nconf.h"
+
+static const char nconf_readme[] = N_(
+"Overview\n"
+"--------\n"
+"Some kernel features may be built directly into the kernel.\n"
+"Some may be made into loadable runtime modules.  Some features\n"
+"may be completely removed altogether.  There are also certain\n"
+"kernel parameters which are not really features, but must be\n"
+"entered in as decimal or hexadecimal numbers or possibly text.\n"
+"\n"
+"Menu items beginning with following braces represent features that\n"
+"  [ ] can be built in or removed\n"
+"  < > can be built in, modularized or removed\n"
+"  { } can be built in or modularized (selected by other feature)\n"
+"  - - are selected by other feature,\n"
+"  XXX cannot be selected. use Symbol Info to find out why,\n"
+"while *, M or whitespace inside braces means to build in, build as\n"
+"a module or to exclude the feature respectively.\n"
+"\n"
+"To change any of these features, highlight it with the cursor\n"
+"keys and press <Y> to build it in, <M> to make it a module or\n"
+"<N> to removed it.  You may also press the <Space Bar> to cycle\n"
+"through the available options (ie. Y->N->M->Y).\n"
+"\n"
+"Some additional keyboard hints:\n"
+"\n"
+"Menus\n"
+"----------\n"
+"o  Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
+"   you wish to change use <Enter> or <Space>. Goto submenu by \n"
+"   pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
+"   Submenus are designated by \"--->\".\n"
+"\n"
+"   Shortcut: Press the option's highlighted letter (hotkey).\n"
+"             Pressing a hotkey more than once will sequence\n"
+"             through all visible items which use that hotkey.\n"
+"\n"
+"   You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
+"   unseen options into view.\n"
+"\n"
+"o  To exit a menu use the just press <ESC> <F5> <F8> or <left-arrow>.\n"
+"\n"
+"o  To get help with an item, press <F1>\n"
+"   Shortcut: Press <h> or <?>.\n"
+"\n"
+"\n"
+"Radiolists  (Choice lists)\n"
+"-----------\n"
+"o  Use the cursor keys to select the option you wish to set and press\n"
+"   <S> or the <SPACE BAR>.\n"
+"\n"
+"   Shortcut: Press the first letter of the option you wish to set then\n"
+"             press <S> or <SPACE BAR>.\n"
+"\n"
+"o  To see available help for the item, press <F1>\n"
+"   Shortcut: Press <H> or <?>.\n"
+"\n"
+"\n"
+"Data Entry\n"
+"-----------\n"
+"o  Enter the requested information and press <ENTER>\n"
+"   If you are entering hexadecimal values, it is not necessary to\n"
+"   add the '0x' prefix to the entry.\n"
+"\n"
+"o  For help, press <F1>.\n"
+"\n"
+"\n"
+"Text Box    (Help Window)\n"
+"--------\n"
+"o  Use the cursor keys to scroll up/down/left/right.  The VI editor\n"
+"   keys h,j,k,l function here as do <SPACE BAR> for those\n"
+"   who are familiar with less and lynx.\n"
+"\n"
+"o  Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n"
+"\n"
+"\n"
+"Alternate Configuration Files\n"
+"-----------------------------\n"
+"nconfig supports the use of alternate configuration files for\n"
+"those who, for various reasons, find it necessary to switch\n"
+"between different kernel configurations.\n"
+"\n"
+"At the end of the main menu you will find two options.  One is\n"
+"for saving the current configuration to a file of your choosing.\n"
+"The other option is for loading a previously saved alternate\n"
+"configuration.\n"
+"\n"
+"Even if you don't use alternate configuration files, but you\n"
+"find during a nconfig session that you have completely messed\n"
+"up your settings, you may use the \"Load Alternate...\" option to\n"
+"restore your previously saved settings from \".config\" without\n"
+"restarting nconfig.\n"
+"\n"
+"Other information\n"
+"-----------------\n"
+"If you use nconfig in an XTERM window make sure you have your\n"
+"$TERM variable set to point to a xterm definition which supports color.\n"
+"Otherwise, nconfig will look rather bad.  nconfig will not\n"
+"display correctly in a RXVT window because rxvt displays only one\n"
+"intensity of color, bright.\n"
+"\n"
+"nconfig will display larger menus on screens or xterms which are\n"
+"set to display more than the standard 25 row by 80 column geometry.\n"
+"In order for this to work, the \"stty size\" command must be able to\n"
+"display the screen's current row and column geometry.  I STRONGLY\n"
+"RECOMMEND that you make sure you do NOT have the shell variables\n"
+"LINES and COLUMNS exported into your environment.  Some distributions\n"
+"export those variables via /etc/profile.  Some ncurses programs can\n"
+"become confused when those variables (LINES & COLUMNS) don't reflect\n"
+"the true screen size.\n"
+"\n"
+"Optional personality available\n"
+"------------------------------\n"
+"If you prefer to have all of the kernel options listed in a single\n"
+"menu, rather than the default multimenu hierarchy, run the nconfig\n"
+"with NCONFIG_MODE environment variable set to single_menu. Example:\n"
+"\n"
+"make NCONFIG_MODE=single_menu nconfig\n"
+"\n"
+"<Enter> will then unroll the appropriate category, or enfold it if it\n"
+"is already unrolled.\n"
+"\n"
+"Note that this mode can eventually be a little more CPU expensive\n"
+"(especially with a larger number of unrolled categories) than the\n"
+"default mode.\n"
+"\n"),
+menu_no_f_instructions[] = N_(
+" You do not have function keys support. Please follow the\n"
+" following instructions:\n"
+" Arrow keys navigate the menu.\n"
+" <Enter> or <right-arrow> selects submenus --->.\n"
+" Capital Letters are hotkeys.\n"
+" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
+" Pressing SpaceBar toggles between the above options\n"
+" Press <Esc> or <left-arrow> to go back one menu, \n"
+" <?> or <h> for Help, </> for Search.\n"
+" <1> is interchangable with <F1>, <2> with <F2>, etc.\n"
+" Legend: [*] built-in  [ ] excluded  <M> module  < > module capable.\n"
+" <Esc> always leaves the current window\n"),
+menu_instructions[] = N_(
+" Arrow keys navigate the menu.\n"
+" <Enter> or <right-arrow> selects submenus --->.\n"
+" Capital Letters are hotkeys.\n"
+" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
+" Pressing SpaceBar toggles between the above options\n"
+" Press <Esc>, <F3> or <left-arrow> to go back one menu, \n"
+" <?>, <F1> or <h> for Help, </> for Search.\n"
+" <1> is interchangable with <F1>, <2> with <F2>, etc.\n"
+" Legend: [*] built-in  [ ] excluded  <M> module  < > module capable.\n"
+" <Esc> always leaves the current window\n"),
+radiolist_instructions[] = N_(
+" Use the arrow keys to navigate this window or\n"
+" press the hotkey of the item you wish to select\n"
+" followed by the <SPACE BAR>.\n"
+" Press <?>, <F1> or <h> for additional information about this option.\n"),
+inputbox_instructions_int[] = N_(
+"Please enter a decimal value.\n"
+"Fractions will not be accepted.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+inputbox_instructions_hex[] = N_(
+"Please enter a hexadecimal value.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+inputbox_instructions_string[] = N_(
+"Please enter a string value.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+setmod_text[] = N_(
+"This feature depends on another which\n"
+"has been configured as a module.\n"
+"As a result, this feature will be built as a module."),
+nohelp_text[] = N_(
+"There is no help available for this kernel option.\n"),
+load_config_text[] = N_(
+"Enter the name of the configuration file you wish to load.\n"
+"Accept the name shown to restore the configuration you\n"
+"last retrieved.  Leave blank to abort."),
+load_config_help[] = N_(
+"\n"
+"For various reasons, one may wish to keep several different kernel\n"
+"configurations available on a single machine.\n"
+"\n"
+"If you have saved a previous configuration in a file other than the\n"
+"kernel's default, entering the name of the file here will allow you\n"
+"to modify that configuration.\n"
+"\n"
+"If you are uncertain, then you have probably never used alternate\n"
+"configuration files.  You should therefor leave this blank to abort.\n"),
+save_config_text[] = N_(
+"Enter a filename to which this configuration should be saved\n"
+"as an alternate.  Leave blank to abort."),
+save_config_help[] = N_(
+"\n"
+"For various reasons, one may wish to keep different kernel\n"
+"configurations available on a single machine.\n"
+"\n"
+"Entering a file name here will allow you to later retrieve, modify\n"
+"and use the current configuration as an alternate to whatever\n"
+"configuration options you have selected at that time.\n"
+"\n"
+"If you are uncertain what all this means then you should probably\n"
+"leave this blank.\n"),
+search_help[] = N_(
+"\n"
+"Search for CONFIG_ symbols and display their relations.\n"
+"Regular expressions are allowed.\n"
+"Example: search for \"^FOO\"\n"
+"Result:\n"
+"-----------------------------------------------------------------\n"
+"Symbol: FOO [ = m]\n"
+"Prompt: Foo bus is used to drive the bar HW\n"
+"Defined at drivers/pci/Kconfig:47\n"
+"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+"Location:\n"
+"  -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
+"    -> PCI support (PCI [ = y])\n"
+"      -> PCI access mode (<choice> [ = y])\n"
+"Selects: LIBCRC32\n"
+"Selected by: BAR\n"
+"-----------------------------------------------------------------\n"
+"o The line 'Prompt:' shows the text used in the menu structure for\n"
+"  this CONFIG_ symbol\n"
+"o The 'Defined at' line tell at what file / line number the symbol\n"
+"  is defined\n"
+"o The 'Depends on:' line tell what symbols needs to be defined for\n"
+"  this symbol to be visible in the menu (selectable)\n"
+"o The 'Location:' lines tell where in the menu structure this symbol\n"
+"  is located\n"
+"    A location followed by a [ = y] indicate that this is a selectable\n"
+"    menu item - and current value is displayed inside brackets.\n"
+"o The 'Selects:' line tell what symbol will be automatically\n"
+"  selected if this symbol is selected (y or m)\n"
+"o The 'Selected by' line tell what symbol has selected this symbol\n"
+"\n"
+"Only relevant lines are shown.\n"
+"\n\n"
+"Search examples:\n"
+"Examples: USB   = > find all CONFIG_ symbols containing USB\n"
+"          ^USB => find all CONFIG_ symbols starting with USB\n"
+"          USB$ => find all CONFIG_ symbols ending with USB\n"
+"\n");
+
+struct mitem {
+       char str[256];
+       char tag;
+       void *usrptr;
+       int is_hot;
+       int is_visible;
+};
+
+#define MAX_MENU_ITEMS 4096
+static int show_all_items;
+static int indent;
+static struct menu *current_menu;
+static int child_count;
+static int single_menu_mode;
+/* the window in which all information appears */
+static WINDOW *main_window;
+/* the largest size of the menu window */
+static int mwin_max_lines;
+static int mwin_max_cols;
+/* the window in which we show option buttons */
+static MENU *curses_menu;
+static ITEM *curses_menu_items[MAX_MENU_ITEMS];
+static struct mitem k_menu_items[MAX_MENU_ITEMS];
+static int items_num;
+static int global_exit;
+/* the currently selected button */
+const char *current_instructions = menu_instructions;
+/* this array is used to implement hot keys. it is updated in item_make and
+ * resetted in clean_items. It would be better to use a hash, but lets keep it
+ * simple... */
+#define MAX_SAME_KEY MAX_MENU_ITEMS
+struct {
+       int count;
+       int ptrs[MAX_MENU_ITEMS];
+} hotkeys[1<<(sizeof(char)*8)];
+
+static void conf(struct menu *menu);
+static void conf_choice(struct menu *menu);
+static void conf_string(struct menu *menu);
+static void conf_load(void);
+static void conf_save(void);
+static void show_help(struct menu *menu);
+static int do_exit(void);
+static void setup_windows(void);
+
+typedef void (*function_key_handler_t)(int *key, struct menu *menu);
+static void handle_f1(int *key, struct menu *current_item);
+static void handle_f2(int *key, struct menu *current_item);
+static void handle_f3(int *key, struct menu *current_item);
+static void handle_f4(int *key, struct menu *current_item);
+static void handle_f5(int *key, struct menu *current_item);
+static void handle_f6(int *key, struct menu *current_item);
+static void handle_f7(int *key, struct menu *current_item);
+static void handle_f8(int *key, struct menu *current_item);
+
+struct function_keys {
+       const char *key_str;
+       const char *func;
+       function_key key;
+       function_key_handler_t handler;
+};
+
+static const int function_keys_num = 8;
+struct function_keys function_keys[] = {
+       {
+               .key_str = "F1",
+               .func = "Help",
+               .key = F_HELP,
+               .handler = handle_f1,
+       },
+       {
+               .key_str = "F2",
+               .func = "Symbol Info",
+               .key = F_SYMBOL,
+               .handler = handle_f2,
+       },
+       {
+               .key_str = "F3",
+               .func = "Instructions",
+               .key = F_INSTS,
+               .handler = handle_f3,
+       },
+       {
+               .key_str = "F4",
+               .func = "Config",
+               .key = F_CONF,
+               .handler = handle_f4,
+       },
+       {
+               .key_str = "F5",
+               .func = "Back",
+               .key = F_BACK,
+               .handler = handle_f5,
+       },
+       {
+               .key_str = "F6",
+               .func = "Save",
+               .key = F_SAVE,
+               .handler = handle_f6,
+       },
+       {
+               .key_str = "F7",
+               .func = "Load",
+               .key = F_LOAD,
+               .handler = handle_f7,
+       },
+       {
+               .key_str = "F8",
+               .func = "Exit",
+               .key = F_EXIT,
+               .handler = handle_f8,
+       },
+};
+
+static void print_function_line(void)
+{
+       int i;
+       int offset = 1;
+       const int skip = 1;
+
+       for (i = 0; i < function_keys_num; i++) {
+               wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);
+               mvwprintw(main_window, LINES-3, offset,
+                               "%s",
+                               function_keys[i].key_str);
+               wattrset(main_window, attributes[FUNCTION_TEXT]);
+               offset += strlen(function_keys[i].key_str);
+               mvwprintw(main_window, LINES-3,
+                               offset, "%s",
+                               function_keys[i].func);
+               offset += strlen(function_keys[i].func) + skip;
+       }
+       wattrset(main_window, attributes[NORMAL]);
+}
+
+/* help */
+static void handle_f1(int *key, struct menu *current_item)
+{
+       show_scroll_win(main_window,
+                       _("README"), _(nconf_readme));
+       return;
+}
+
+/* symbole help */
+static void handle_f2(int *key, struct menu *current_item)
+{
+       show_help(current_item);
+       return;
+}
+
+/* instructions */
+static void handle_f3(int *key, struct menu *current_item)
+{
+       show_scroll_win(main_window,
+                       _("Instructions"),
+                       _(current_instructions));
+       return;
+}
+
+/* config */
+static void handle_f4(int *key, struct menu *current_item)
+{
+       int res = btn_dialog(main_window,
+                       _("Show all symbols?"),
+                       2,
+                       "   <Show All>   ",
+                       "<Don't show all>");
+       if (res == 0)
+               show_all_items = 1;
+       else if (res == 1)
+               show_all_items = 0;
+
+       return;
+}
+
+/* back */
+static void handle_f5(int *key, struct menu *current_item)
+{
+       *key = KEY_LEFT;
+       return;
+}
+
+/* save */
+static void handle_f6(int *key, struct menu *current_item)
+{
+       conf_save();
+       return;
+}
+
+/* load */
+static void handle_f7(int *key, struct menu *current_item)
+{
+       conf_load();
+       return;
+}
+
+/* exit */
+static void handle_f8(int *key, struct menu *current_item)
+{
+       do_exit();
+       return;
+}
+
+/* return != 0 to indicate the key was handles */
+static int process_special_keys(int *key, struct menu *menu)
+{
+       int i;
+
+       if (*key == KEY_RESIZE) {
+               setup_windows();
+               return 1;
+       }
+
+       for (i = 0; i < function_keys_num; i++) {
+               if (*key == KEY_F(function_keys[i].key) ||
+                   *key == '0' + function_keys[i].key){
+                       function_keys[i].handler(key, menu);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static void clean_items(void)
+{
+       int i;
+       for (i = 0; curses_menu_items[i]; i++)
+               free_item(curses_menu_items[i]);
+       bzero(curses_menu_items, sizeof(curses_menu_items));
+       bzero(k_menu_items, sizeof(k_menu_items));
+       bzero(hotkeys, sizeof(hotkeys));
+       items_num = 0;
+}
+
+/* return the index of the next hot item, or -1 if no such item exists */
+static int get_next_hot(int c)
+{
+       static int hot_index;
+       static int hot_char;
+
+       if (c < 0 || c > 255 || hotkeys[c].count <= 0)
+               return -1;
+
+       if (hot_char == c) {
+               hot_index = (hot_index+1)%hotkeys[c].count;
+               return hotkeys[c].ptrs[hot_index];
+       } else {
+               hot_char = c;
+               hot_index = 0;
+               return hotkeys[c].ptrs[0];
+       }
+}
+
+/* can the char c be a hot key? no, if c is a common shortcut used elsewhere */
+static int canbhot(char c)
+{
+       c = tolower(c);
+       return isalnum(c) && c != 'y' && c != 'm' && c != 'h' &&
+               c != 'n' && c != '?';
+}
+
+/* check if str already contains a hot key. */
+static int is_hot(int index)
+{
+       return k_menu_items[index].is_hot;
+}
+
+/* find the first possible hot key, and mark it.
+ * index is the index of the item in the menu
+ * return 0 on success*/
+static int make_hot(char *dest, int len, const char *org, int index)
+{
+       int position = -1;
+       int i;
+       int tmp;
+       int c;
+       int org_len = strlen(org);
+
+       if (org == NULL || is_hot(index))
+               return 1;
+
+       /* make sure not to make hot keys out of markers.
+        * find where to start looking for a hot key
+        */
+       i = 0;
+       /* skip white space */
+       while (i < org_len && org[i] == ' ')
+               i++;
+       if (i == org_len)
+               return -1;
+       /* if encountering '(' or '<' or '[', find the match and look from there
+        **/
+       if (org[i] == '[' || org[i] == '<' || org[i] == '(') {
+               i++;
+               for (; i < org_len; i++)
+                       if (org[i] == ']' || org[i] == '>' || org[i] == ')')
+                               break;
+       }
+       if (i == org_len)
+               return -1;
+       for (; i < org_len; i++) {
+               if (canbhot(org[i]) && org[i-1] != '<' && org[i-1] != '(') {
+                       position = i;
+                       break;
+               }
+       }
+       if (position == -1)
+               return 1;
+
+       /* ok, char at org[position] should be a hot key to this item */
+       c = tolower(org[position]);
+       tmp = hotkeys[c].count;
+       hotkeys[c].ptrs[tmp] = index;
+       hotkeys[c].count++;
+       /*
+          snprintf(dest, len, "%.*s(%c)%s", position, org, org[position],
+          &org[position+1]);
+          */
+       /* make org[position] uppercase, and all leading letter small case */
+       strncpy(dest, org, len);
+       for (i = 0; i < position; i++)
+               dest[i] = tolower(dest[i]);
+       dest[position] = toupper(dest[position]);
+       k_menu_items[index].is_hot = 1;
+       return 0;
+}
+
+/* Make a new item. Add a hotkey mark in the first possible letter.
+ * As ncurses does not allow any attributes inside menue item, we mark the
+ * hot key as the first capitalized letter in the string */
+static void item_make(struct menu *menu, char tag, const char *fmt, ...)
+{
+       va_list ap;
+       char tmp_str[256];
+
+       if (items_num > MAX_MENU_ITEMS-1)
+               return;
+
+       bzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));
+       k_menu_items[items_num].tag = tag;
+       k_menu_items[items_num].usrptr = menu;
+       if (menu != NULL)
+               k_menu_items[items_num].is_visible =
+                       menu_is_visible(menu);
+       else
+               k_menu_items[items_num].is_visible = 1;
+
+       va_start(ap, fmt);
+       vsnprintf(tmp_str, sizeof(tmp_str), fmt, ap);
+       if (!k_menu_items[items_num].is_visible)
+               memcpy(tmp_str, "XXX", 3);
+       va_end(ap);
+       if (make_hot(
+               k_menu_items[items_num].str,
+               sizeof(k_menu_items[items_num].str), tmp_str, items_num) != 0)
+               strncpy(k_menu_items[items_num].str,
+                       tmp_str,
+                       sizeof(k_menu_items[items_num].str));
+
+       curses_menu_items[items_num] = new_item(
+                       k_menu_items[items_num].str,
+                       k_menu_items[items_num].str);
+       set_item_userptr(curses_menu_items[items_num],
+                       &k_menu_items[items_num]);
+       /*
+       if (!k_menu_items[items_num].is_visible)
+               item_opts_off(curses_menu_items[items_num], O_SELECTABLE);
+       */
+
+       items_num++;
+       curses_menu_items[items_num] = NULL;
+}
+
+/* very hackish. adds a string to the last item added */
+static void item_add_str(const char *fmt, ...)
+{
+       va_list ap;
+       int index = items_num-1;
+       char new_str[256];
+       char tmp_str[256];
+
+       if (index < 0)
+               return;
+
+       va_start(ap, fmt);
+       vsnprintf(new_str, sizeof(new_str), fmt, ap);
+       va_end(ap);
+       snprintf(tmp_str, sizeof(tmp_str), "%s%s",
+                       k_menu_items[index].str, new_str);
+       if (make_hot(k_menu_items[index].str,
+                       sizeof(k_menu_items[index].str), tmp_str, index) != 0)
+               strncpy(k_menu_items[index].str,
+                       tmp_str,
+                       sizeof(k_menu_items[index].str));
+
+       free_item(curses_menu_items[index]);
+       curses_menu_items[index] = new_item(
+                       k_menu_items[index].str,
+                       k_menu_items[index].str);
+       set_item_userptr(curses_menu_items[index],
+                       &k_menu_items[index]);
+}
+
+/* get the tag of the currently selected item */
+static char item_tag(void)
+{
+       ITEM *cur;
+       struct mitem *mcur;
+
+       cur = current_item(curses_menu);
+       if (cur == NULL)
+               return 0;
+       mcur = (struct mitem *) item_userptr(cur);
+       return mcur->tag;
+}
+
+static int curses_item_index(void)
+{
+       return  item_index(current_item(curses_menu));
+}
+
+static void *item_data(void)
+{
+       ITEM *cur;
+       struct mitem *mcur;
+
+       cur = current_item(curses_menu);
+       mcur = (struct mitem *) item_userptr(cur);
+       return mcur->usrptr;
+
+}
+
+static int item_is_tag(char tag)
+{
+       return item_tag() == tag;
+}
+
+static char filename[PATH_MAX+1];
+static char menu_backtitle[PATH_MAX+128];
+static const char *set_config_filename(const char *config_filename)
+{
+       int size;
+       struct symbol *sym;
+
+       sym = sym_lookup("KERNELVERSION", 0);
+       sym_calc_value(sym);
+       size = snprintf(menu_backtitle, sizeof(menu_backtitle),
+                       _("%s - Linux Kernel v%s Configuration"),
+                       config_filename, sym_get_string_value(sym));
+       if (size >= sizeof(menu_backtitle))
+               menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
+
+       size = snprintf(filename, sizeof(filename), "%s", config_filename);
+       if (size >= sizeof(filename))
+               filename[sizeof(filename)-1] = '\0';
+       return menu_backtitle;
+}
+
+/* command = 0 is supress, 1 is restore */
+static void supress_stdout(int command)
+{
+       static FILE *org_stdout;
+       static FILE *org_stderr;
+
+       if (command == 0) {
+               org_stdout = stdout;
+               org_stderr = stderr;
+               stdout = fopen("/dev/null", "a");
+               stderr = fopen("/dev/null", "a");
+       } else {
+               fclose(stdout);
+               fclose(stderr);
+               stdout = org_stdout;
+               stderr = org_stderr;
+       }
+}
+
+/* return = 0 means we are successful.
+ * -1 means go on doing what you were doing
+ */
+static int do_exit(void)
+{
+       int res;
+       if (!conf_get_changed()) {
+               global_exit = 1;
+               return 0;
+       }
+       res = btn_dialog(main_window,
+                       _("Do you wish to save your "
+                               "new kernel configuration?\n"
+                               "<ESC> to cancel and resume nconfig."),
+                       2,
+                       "   <save>   ",
+                       "<don't save>");
+       if (res == KEY_EXIT) {
+               global_exit = 0;
+               return -1;
+       }
+
+       /* if we got here, the user really wants to exit */
+       switch (res) {
+       case 0:
+               supress_stdout(0);
+               res = conf_write(filename);
+               supress_stdout(1);
+               if (res)
+                       btn_dialog(
+                               main_window,
+                               _("Error during writing of the kernel "
+                                 "configuration.\n"
+                                 "Your kernel configuration "
+                                 "changes were NOT saved."),
+                                 1,
+                                 "<OK>");
+               else {
+                       char buf[1024];
+                       snprintf(buf, 1024,
+                               _("Configuration written to %s\n"
+                                 "End of Linux kernel configuration.\n"
+                                 "Execute 'make' to build the kernel or try"
+                                 " 'make help'."), filename);
+                       btn_dialog(
+                               main_window,
+                               buf,
+                               1,
+                               "<OK>");
+               }
+               break;
+       default:
+               btn_dialog(
+                       main_window,
+                       _("Your kernel configuration changes were NOT saved."),
+                       1,
+                       "<OK>");
+               break;
+       }
+       global_exit = 1;
+       return 0;
+}
+
+
+static void search_conf(void)
+{
+       struct symbol **sym_arr;
+       struct gstr res;
+       char dialog_input_result[100];
+       char *dialog_input;
+       int dres;
+again:
+       dres = dialog_inputbox(main_window,
+                       _("Search Configuration Parameter"),
+                       _("Enter CONFIG_ (sub)string to search for "
+                               "(with or without \"CONFIG\")"),
+                       "", dialog_input_result, 99);
+       switch (dres) {
+       case 0:
+               break;
+       case 1:
+               show_scroll_win(main_window,
+                               _("Search Configuration"), search_help);
+               goto again;
+       default:
+               return;
+       }
+
+       /* strip CONFIG_ if necessary */
+       dialog_input = dialog_input_result;
+       if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
+               dialog_input += 7;
+
+       sym_arr = sym_re_search(dialog_input);
+       res = get_relations_str(sym_arr);
+       free(sym_arr);
+       show_scroll_win(main_window,
+                       _("Search Results"), str_get(&res));
+       str_free(&res);
+}
+
+
+static void build_conf(struct menu *menu)
+{
+       struct symbol *sym;
+       struct property *prop;
+       struct menu *child;
+       int type, tmp, doint = 2;
+       tristate val;
+       char ch;
+
+       if (!menu || (!show_all_items && !menu_is_visible(menu)))
+               return;
+
+       sym = menu->sym;
+       prop = menu->prompt;
+       if (!sym) {
+               if (prop && menu != current_menu) {
+                       const char *prompt = menu_get_prompt(menu);
+                       enum prop_type ptype;
+                       ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+                       switch (ptype) {
+                       case P_MENU:
+                               child_count++;
+                               prompt = _(prompt);
+                               if (single_menu_mode) {
+                                       item_make(menu, 'm',
+                                               "%s%*c%s",
+                                               menu->data ? "-->" : "++>",
+                                               indent + 1, ' ', prompt);
+                               } else
+                                       item_make(menu, 'm',
+                                               "   %*c%s  --->",
+                                               indent + 1,
+                                               ' ', prompt);
+
+                               if (single_menu_mode && menu->data)
+                                       goto conf_childs;
+                               return;
+                       case P_COMMENT:
+                               if (prompt) {
+                                       child_count++;
+                                       item_make(menu, ':',
+                                               "   %*c*** %s ***",
+                                               indent + 1, ' ',
+                                               _(prompt));
+                               }
+                               break;
+                       default:
+                               if (prompt) {
+                                       child_count++;
+                                       item_make(menu, ':', "---%*c%s",
+                                               indent + 1, ' ',
+                                               _(prompt));
+                               }
+                       }
+               } else
+                       doint = 0;
+               goto conf_childs;
+       }
+
+       type = sym_get_type(sym);
+       if (sym_is_choice(sym)) {
+               struct symbol *def_sym = sym_get_choice_value(sym);
+               struct menu *def_menu = NULL;
+
+               child_count++;
+               for (child = menu->list; child; child = child->next) {
+                       if (menu_is_visible(child) && child->sym == def_sym)
+                               def_menu = child;
+               }
+
+               val = sym_get_tristate_value(sym);
+               if (sym_is_changable(sym)) {
+                       switch (type) {
+                       case S_BOOLEAN:
+                               item_make(menu, 't', "[%c]",
+                                               val == no ? ' ' : '*');
+                               break;
+                       case S_TRISTATE:
+                               switch (val) {
+                               case yes:
+                                       ch = '*';
+                                       break;
+                               case mod:
+                                       ch = 'M';
+                                       break;
+                               default:
+                                       ch = ' ';
+                                       break;
+                               }
+                               item_make(menu, 't', "<%c>", ch);
+                               break;
+                       }
+               } else {
+                       item_make(menu, def_menu ? 't' : ':', "   ");
+               }
+
+               item_add_str("%*c%s", indent + 1,
+                               ' ', _(menu_get_prompt(menu)));
+               if (val == yes) {
+                       if (def_menu) {
+                               item_add_str(" (%s)",
+                                       _(menu_get_prompt(def_menu)));
+                               item_add_str("  --->");
+                               if (def_menu->list) {
+                                       indent += 2;
+                                       build_conf(def_menu);
+                                       indent -= 2;
+                               }
+                       }
+                       return;
+               }
+       } else {
+               if (menu == current_menu) {
+                       item_make(menu, ':',
+                               "---%*c%s", indent + 1,
+                               ' ', _(menu_get_prompt(menu)));
+                       goto conf_childs;
+               }
+               child_count++;
+               val = sym_get_tristate_value(sym);
+               if (sym_is_choice_value(sym) && val == yes) {
+                       item_make(menu, ':', "   ");
+               } else {
+                       switch (type) {
+                       case S_BOOLEAN:
+                               if (sym_is_changable(sym))
+                                       item_make(menu, 't', "[%c]",
+                                               val == no ? ' ' : '*');
+                               else
+                                       item_make(menu, 't', "-%c-",
+                                               val == no ? ' ' : '*');
+                               break;
+                       case S_TRISTATE:
+                               switch (val) {
+                               case yes:
+                                       ch = '*';
+                                       break;
+                               case mod:
+                                       ch = 'M';
+                                       break;
+                               default:
+                                       ch = ' ';
+                                       break;
+                               }
+                               if (sym_is_changable(sym)) {
+                                       if (sym->rev_dep.tri == mod)
+                                               item_make(menu,
+                                                       't', "{%c}", ch);
+                                       else
+                                               item_make(menu,
+                                                       't', "<%c>", ch);
+                               } else
+                                       item_make(menu, 't', "-%c-", ch);
+                               break;
+                       default:
+                               tmp = 2 + strlen(sym_get_string_value(sym));
+                               item_make(menu, 's', "    (%s)",
+                                               sym_get_string_value(sym));
+                               tmp = indent - tmp + 4;
+                               if (tmp < 0)
+                                       tmp = 0;
+                               item_add_str("%*c%s%s", tmp, ' ',
+                                               _(menu_get_prompt(menu)),
+                                               (sym_has_value(sym) ||
+                                                !sym_is_changable(sym)) ? "" :
+                                               _(" (NEW)"));
+                               goto conf_childs;
+                       }
+               }
+               item_add_str("%*c%s%s", indent + 1, ' ',
+                               _(menu_get_prompt(menu)),
+                               (sym_has_value(sym) || !sym_is_changable(sym)) ?
+                               "" : _(" (NEW)"));
+               if (menu->prompt && menu->prompt->type == P_MENU) {
+                       item_add_str("  --->");
+                       return;
+               }
+       }
+
+conf_childs:
+       indent += doint;
+       for (child = menu->list; child; child = child->next)
+               build_conf(child);
+       indent -= doint;
+}
+
+static void reset_menu(void)
+{
+       unpost_menu(curses_menu);
+       clean_items();
+}
+
+/* adjust the menu to show this item.
+ * prefer not to scroll the menu if possible*/
+static void center_item(int selected_index, int *last_top_row)
+{
+       int toprow;
+       int maxy, maxx;
+
+       scale_menu(curses_menu, &maxy, &maxx);
+       set_top_row(curses_menu, *last_top_row);
+       toprow = top_row(curses_menu);
+       if (selected_index >= toprow && selected_index < toprow+maxy) {
+               /* we can only move the selected item. no need to scroll */
+               set_current_item(curses_menu,
+                               curses_menu_items[selected_index]);
+       } else {
+               toprow = max(selected_index-maxy/2, 0);
+               if (toprow >= item_count(curses_menu)-maxy)
+                       toprow = item_count(curses_menu)-mwin_max_lines;
+               set_top_row(curses_menu, toprow);
+               set_current_item(curses_menu,
+                               curses_menu_items[selected_index]);
+       }
+       *last_top_row = toprow;
+       post_menu(curses_menu);
+       refresh_all_windows(main_window);
+}
+
+/* this function assumes reset_menu has been called before */
+static void show_menu(const char *prompt, const char *instructions,
+               int selected_index, int *last_top_row)
+{
+       int maxx, maxy;
+       WINDOW *menu_window;
+
+       current_instructions = instructions;
+
+       clear();
+       wattrset(main_window, attributes[NORMAL]);
+       print_in_middle(stdscr, 1, 0, COLS,
+                       menu_backtitle,
+                       attributes[MAIN_HEADING]);
+
+       wattrset(main_window, attributes[MAIN_MENU_BOX]);
+       box(main_window, 0, 0);
+       wattrset(main_window, attributes[MAIN_MENU_HEADING]);
+       mvwprintw(main_window, 0, 3, " %s ", prompt);
+       wattrset(main_window, attributes[NORMAL]);
+
+       set_menu_items(curses_menu, curses_menu_items);
+
+       /* position the menu at the middle of the screen */
+       scale_menu(curses_menu, &maxy, &maxx);
+       maxx = min(maxx, mwin_max_cols-2);
+       maxy = mwin_max_lines-2;
+       menu_window = derwin(main_window,
+                       maxy,
+                       maxx,
+                       2,
+                       (mwin_max_cols-maxx)/2);
+       keypad(menu_window, TRUE);
+       set_menu_win(curses_menu, menu_window);
+       set_menu_sub(curses_menu, menu_window);
+
+       /* must reassert this after changing items, otherwise returns to a
+        * default of 16
+        */
+       set_menu_format(curses_menu, maxy, 1);
+       center_item(selected_index, last_top_row);
+       set_menu_format(curses_menu, maxy, 1);
+
+       print_function_line();
+
+       /* Post the menu */
+       post_menu(curses_menu);
+       refresh_all_windows(main_window);
+}
+
+
+static void conf(struct menu *menu)
+{
+       char pattern[256];
+       struct menu *submenu = 0;
+       const char *prompt = menu_get_prompt(menu);
+       struct symbol *sym;
+       struct menu *active_menu = NULL;
+       int res;
+       int current_index = 0;
+       int last_top_row = 0;
+
+       bzero(pattern, sizeof(pattern));
+
+       while (!global_exit) {
+               reset_menu();
+               current_menu = menu;
+               build_conf(menu);
+               if (!child_count)
+                       break;
+
+               show_menu(prompt ? _(prompt) : _("Main Menu"),
+                               _(menu_instructions),
+                               current_index, &last_top_row);
+               keypad((menu_win(curses_menu)), TRUE);
+               while (!global_exit && (res = wgetch(menu_win(curses_menu)))) {
+                       if (process_special_keys(&res,
+                                               (struct menu *) item_data()))
+                               break;
+                       switch (res) {
+                       case KEY_DOWN:
+                               menu_driver(curses_menu, REQ_DOWN_ITEM);
+                               break;
+                       case KEY_UP:
+                               menu_driver(curses_menu, REQ_UP_ITEM);
+                               break;
+                       case KEY_NPAGE:
+                               menu_driver(curses_menu, REQ_SCR_DPAGE);
+                               break;
+                       case KEY_PPAGE:
+                               menu_driver(curses_menu, REQ_SCR_UPAGE);
+                               break;
+                       case KEY_HOME:
+                               menu_driver(curses_menu, REQ_FIRST_ITEM);
+                               break;
+                       case KEY_END:
+                               menu_driver(curses_menu, REQ_LAST_ITEM);
+                               break;
+                       case 'h':
+                       case '?':
+                               show_help((struct menu *) item_data());
+                               break;
+                       }
+                       if (res == 10 || res == 27 ||
+                               res == 32 || res == 'n' || res == 'y' ||
+                               res == KEY_LEFT || res == KEY_RIGHT ||
+                               res == 'm' || res == '/')
+                               break;
+                       else if (canbhot(res)) {
+                               /* check for hot keys: */
+                               int tmp = get_next_hot(res);
+                               if (tmp != -1)
+                                       center_item(tmp, &last_top_row);
+                       }
+                       refresh_all_windows(main_window);
+               }
+
+               refresh_all_windows(main_window);
+               /* if ESC  or left*/
+               if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
+                       break;
+
+               /* remember location in the menu */
+               last_top_row = top_row(curses_menu);
+               current_index = curses_item_index();
+
+               if (!item_tag())
+                       continue;
+
+               submenu = (struct menu *) item_data();
+               active_menu = (struct menu *)item_data();
+               if (!submenu || !menu_is_visible(submenu))
+                       continue;
+               if (submenu)
+                       sym = submenu->sym;
+               else
+                       sym = NULL;
+
+               switch (res) {
+               case ' ':
+                       if (item_is_tag('t'))
+                               sym_toggle_tristate_value(sym);
+                       else if (item_is_tag('m'))
+                               conf(submenu);
+                       break;
+               case KEY_RIGHT:
+               case 10: /* ENTER WAS PRESSED */
+                       switch (item_tag()) {
+                       case 'm':
+                               if (single_menu_mode)
+                                       submenu->data =
+                                               (void *) (long) !submenu->data;
+                               else
+                                       conf(submenu);
+                               break;
+                       case 't':
+                               if (sym_is_choice(sym) &&
+                                   sym_get_tristate_value(sym) == yes)
+                                       conf_choice(submenu);
+                               else if (submenu->prompt &&
+                                        submenu->prompt->type == P_MENU)
+                                       conf(submenu);
+                               else if (res == 10)
+                                       sym_toggle_tristate_value(sym);
+                               break;
+                       case 's':
+                               conf_string(submenu);
+                               break;
+                       }
+                       break;
+               case 'y':
+                       if (item_is_tag('t')) {
+                               if (sym_set_tristate_value(sym, yes))
+                                       break;
+                               if (sym_set_tristate_value(sym, mod))
+                                       btn_dialog(main_window, setmod_text, 0);
+                       }
+                       break;
+               case 'n':
+                       if (item_is_tag('t'))
+                               sym_set_tristate_value(sym, no);
+                       break;
+               case 'm':
+                       if (item_is_tag('t'))
+                               sym_set_tristate_value(sym, mod);
+                       break;
+               case '/':
+                       search_conf();
+                       break;
+               }
+       }
+}
+
+static void show_help(struct menu *menu)
+{
+       struct gstr help = str_new();
+
+       if (menu && menu->sym && menu_has_help(menu)) {
+               if (menu->sym->name) {
+                       str_printf(&help, "CONFIG_%s:\n\n", menu->sym->name);
+                       str_append(&help, _(menu_get_help(menu)));
+                       str_append(&help, "\n");
+                       get_symbol_str(&help, menu->sym);
+               }
+       } else {
+               str_append(&help, nohelp_text);
+       }
+       show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));
+       str_free(&help);
+}
+
+static void conf_choice(struct menu *menu)
+{
+       const char *prompt = _(menu_get_prompt(menu));
+       struct menu *child = 0;
+       struct symbol *active;
+       int selected_index = 0;
+       int last_top_row = 0;
+       int res, i = 0;
+
+       active = sym_get_choice_value(menu->sym);
+       /* this is mostly duplicated from the conf() function. */
+       while (!global_exit) {
+               reset_menu();
+
+               for (i = 0, child = menu->list; child; child = child->next) {
+                       if (!show_all_items && !menu_is_visible(child))
+                               continue;
+
+                       if (child->sym == sym_get_choice_value(menu->sym))
+                               item_make(child, ':', "<X> %s",
+                                               _(menu_get_prompt(child)));
+                       else
+                               item_make(child, ':', "    %s",
+                                               _(menu_get_prompt(child)));
+                       if (child->sym == active){
+                               last_top_row = top_row(curses_menu);
+                               selected_index = i;
+                       }
+                       i++;
+               }
+               show_menu(prompt ? _(prompt) : _("Choice Menu"),
+                               _(radiolist_instructions),
+                               selected_index,
+                               &last_top_row);
+               while (!global_exit && (res = wgetch(menu_win(curses_menu)))) {
+                       if (process_special_keys(
+                                               &res,
+                                               (struct menu *) item_data()))
+                               break;
+                       switch (res) {
+                       case KEY_DOWN:
+                               menu_driver(curses_menu, REQ_DOWN_ITEM);
+                               break;
+                       case KEY_UP:
+                               menu_driver(curses_menu, REQ_UP_ITEM);
+                               break;
+                       case KEY_NPAGE:
+                               menu_driver(curses_menu, REQ_SCR_DPAGE);
+                               break;
+                       case KEY_PPAGE:
+                               menu_driver(curses_menu, REQ_SCR_UPAGE);
+                               break;
+                       case KEY_HOME:
+                               menu_driver(curses_menu, REQ_FIRST_ITEM);
+                               break;
+                       case KEY_END:
+                               menu_driver(curses_menu, REQ_LAST_ITEM);
+                               break;
+                       case 'h':
+                       case '?':
+                               show_help((struct menu *) item_data());
+                               break;
+                       }
+                       if (res == 10 || res == 27 || res == ' ' ||
+                               res == KEY_LEFT)
+                               break;
+                       else if (canbhot(res)) {
+                               /* check for hot keys: */
+                               int tmp = get_next_hot(res);
+                               if (tmp != -1)
+                                       center_item(tmp, &last_top_row);
+                       }
+                       refresh_all_windows(main_window);
+               }
+               /* if ESC or left */
+               if (res == 27 || res == KEY_LEFT)
+                       break;
+
+               child = item_data();
+               if (!child || !menu_is_visible(child))
+                       continue;
+               switch (res) {
+               case ' ':
+               case  10:
+               case KEY_RIGHT:
+                       sym_set_tristate_value(child->sym, yes);
+                       return;
+               case 'h':
+               case '?':
+                       show_help(child);
+                       active = child->sym;
+                       break;
+               case KEY_EXIT:
+                       return;
+               }
+       }
+}
+
+static void conf_string(struct menu *menu)
+{
+       const char *prompt = menu_get_prompt(menu);
+       char dialog_input_result[256];
+
+       while (1) {
+               int res;
+               const char *heading;
+
+               switch (sym_get_type(menu->sym)) {
+               case S_INT:
+                       heading = _(inputbox_instructions_int);
+                       break;
+               case S_HEX:
+                       heading = _(inputbox_instructions_hex);
+                       break;
+               case S_STRING:
+                       heading = _(inputbox_instructions_string);
+                       break;
+               default:
+                       heading = _("Internal nconf error!");
+               }
+               res = dialog_inputbox(main_window,
+                               prompt ? _(prompt) : _("Main Menu"),
+                               heading,
+                               sym_get_string_value(menu->sym),
+                               dialog_input_result,
+                               sizeof(dialog_input_result));
+               switch (res) {
+               case 0:
+                       if (sym_set_string_value(menu->sym,
+                                               dialog_input_result))
+                               return;
+                       btn_dialog(main_window,
+                               _("You have made an invalid entry."), 0);
+                       break;
+               case 1:
+                       show_help(menu);
+                       break;
+               case KEY_EXIT:
+                       return;
+               }
+       }
+}
+
+static void conf_load(void)
+{
+       char dialog_input_result[256];
+       while (1) {
+               int res;
+               res = dialog_inputbox(main_window,
+                               NULL, load_config_text,
+                               filename,
+                               dialog_input_result,
+                               sizeof(dialog_input_result));
+               switch (res) {
+               case 0:
+                       if (!dialog_input_result[0])
+                               return;
+                       if (!conf_read(dialog_input_result)) {
+                               set_config_filename(dialog_input_result);
+                               sym_set_change_count(1);
+                               return;
+                       }
+                       btn_dialog(main_window, _("File does not exist!"), 0);
+                       break;
+               case 1:
+                       show_scroll_win(main_window,
+                                       _("Load Alternate Configuration"),
+                                       load_config_help);
+                       break;
+               case KEY_EXIT:
+                       return;
+               }
+       }
+}
+
+static void conf_save(void)
+{
+       char dialog_input_result[256];
+       while (1) {
+               int res;
+               res = dialog_inputbox(main_window,
+                               NULL, save_config_text,
+                               filename,
+                               dialog_input_result,
+                               sizeof(dialog_input_result));
+               switch (res) {
+               case 0:
+                       if (!dialog_input_result[0])
+                               return;
+                       supress_stdout(0);
+                       res = conf_write(dialog_input_result);
+                       supress_stdout(1);
+                       if (!res) {
+                               char buf[1024];
+                               sprintf(buf, "%s %s",
+                                       _("configuration file saved to: "),
+                                       dialog_input_result);
+                               btn_dialog(main_window,
+                                          buf, 1, "<OK>");
+                               set_config_filename(dialog_input_result);
+                               return;
+                       }
+                       btn_dialog(main_window, _("Can't create file! "
+                               "Probably a nonexistent directory."),
+                               1, "<OK>");
+                       break;
+               case 1:
+                       show_scroll_win(main_window,
+                               _("Save Alternate Configuration"),
+                               save_config_help);
+                       break;
+               case KEY_EXIT:
+                       return;
+               }
+       }
+}
+
+void setup_windows(void)
+{
+       if (main_window != NULL)
+               delwin(main_window);
+
+       /* set up the menu and menu window */
+       main_window = newwin(LINES-2, COLS-2, 2, 1);
+       keypad(main_window, TRUE);
+       mwin_max_lines = LINES-6;
+       mwin_max_cols = COLS-6;
+
+       /* panels order is from bottom to top */
+       new_panel(main_window);
+}
+
+int main(int ac, char **av)
+{
+       char *mode;
+
+       setlocale(LC_ALL, "");
+       bindtextdomain(PACKAGE, LOCALEDIR);
+       textdomain(PACKAGE);
+
+       conf_parse(av[1]);
+       conf_read(NULL);
+
+       mode = getenv("NCONFIG_MODE");
+       if (mode) {
+               if (!strcasecmp(mode, "single_menu"))
+                       single_menu_mode = 1;
+       }
+
+       /* Initialize curses */
+       initscr();
+       /* set color theme */
+       set_colors();
+
+       cbreak();
+       noecho();
+       keypad(stdscr, TRUE);
+       curs_set(0);
+
+       if (COLS < 75 || LINES < 20) {
+               endwin();
+               printf("Your terminal should have at "
+                       "least 20 lines and 75 columns\n");
+               return 1;
+       }
+
+       notimeout(stdscr, FALSE);
+       ESCDELAY = 1;
+
+       /* set btns menu */
+       curses_menu = new_menu(curses_menu_items);
+       menu_opts_off(curses_menu, O_SHOWDESC);
+       menu_opts_off(curses_menu, O_SHOWMATCH);
+       menu_opts_on(curses_menu, O_ONEVALUE);
+       menu_opts_on(curses_menu, O_NONCYCLIC);
+       set_menu_mark(curses_menu, " ");
+       set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
+       set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
+       set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]);
+
+       set_config_filename(conf_get_configname());
+       setup_windows();
+
+       /* check for KEY_FUNC(1) */
+       if (has_key(KEY_F(1)) == FALSE) {
+               show_scroll_win(main_window,
+                               _("Instructions"),
+                               _(menu_no_f_instructions));
+       }
+
+
+
+       /* do the work */
+       while (!global_exit) {
+               conf(&rootmenu);
+               if (!global_exit && do_exit() == 0)
+                       break;
+       }
+       /* ok, we are done */
+       unpost_menu(curses_menu);
+       free_menu(curses_menu);
+       delwin(main_window);
+       clear();
+       refresh();
+       endwin();
+       return 0;
+}
+
diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
new file mode 100644 (file)
index 0000000..115edb4
--- /dev/null
@@ -0,0 +1,617 @@
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+#include "nconf.h"
+
+/* a list of all the different widgets we use */
+attributes_t attributes[ATTR_MAX+1] = {0};
+
+/* available colors:
+   COLOR_BLACK   0
+   COLOR_RED     1
+   COLOR_GREEN   2
+   COLOR_YELLOW  3
+   COLOR_BLUE    4
+   COLOR_MAGENTA 5
+   COLOR_CYAN    6
+   COLOR_WHITE   7
+   */
+static void set_normal_colors(void)
+{
+       init_pair(NORMAL, -1, -1);
+       init_pair(MAIN_HEADING, COLOR_MAGENTA, -1);
+
+       /* FORE is for the selected item */
+       init_pair(MAIN_MENU_FORE, -1, -1);
+       /* BACK for all the rest */
+       init_pair(MAIN_MENU_BACK, -1, -1);
+       init_pair(MAIN_MENU_GREY, -1, -1);
+       init_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1);
+       init_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1);
+
+       init_pair(SCROLLWIN_TEXT, -1, -1);
+       init_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1);
+       init_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1);
+
+       init_pair(DIALOG_TEXT, -1, -1);
+       init_pair(DIALOG_BOX, COLOR_YELLOW, -1);
+       init_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1);
+       init_pair(DIALOG_MENU_FORE, COLOR_RED, -1);
+
+       init_pair(INPUT_BOX, COLOR_YELLOW, -1);
+       init_pair(INPUT_HEADING, COLOR_GREEN, -1);
+       init_pair(INPUT_TEXT, -1, -1);
+       init_pair(INPUT_FIELD, -1, -1);
+
+       init_pair(FUNCTION_HIGHLIGHT, -1, -1);
+       init_pair(FUNCTION_TEXT, COLOR_BLUE, -1);
+}
+
+/* available attributes:
+   A_NORMAL        Normal display (no highlight)
+   A_STANDOUT      Best highlighting mode of the terminal.
+   A_UNDERLINE     Underlining
+   A_REVERSE       Reverse video
+   A_BLINK         Blinking
+   A_DIM           Half bright
+   A_BOLD          Extra bright or bold
+   A_PROTECT       Protected mode
+   A_INVIS         Invisible or blank mode
+   A_ALTCHARSET    Alternate character set
+   A_CHARTEXT      Bit-mask to extract a character
+   COLOR_PAIR(n)   Color-pair number n
+   */
+static void normal_color_theme(void)
+{
+       /* automatically add color... */
+#define mkattr(name, attr) do { \
+attributes[name] = attr | COLOR_PAIR(name); } while (0)
+       mkattr(NORMAL, NORMAL);
+       mkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE);
+
+       mkattr(MAIN_MENU_FORE, A_REVERSE);
+       mkattr(MAIN_MENU_BACK, A_NORMAL);
+       mkattr(MAIN_MENU_GREY, A_NORMAL);
+       mkattr(MAIN_MENU_HEADING, A_BOLD);
+       mkattr(MAIN_MENU_BOX, A_NORMAL);
+
+       mkattr(SCROLLWIN_TEXT, A_NORMAL);
+       mkattr(SCROLLWIN_HEADING, A_BOLD);
+       mkattr(SCROLLWIN_BOX, A_BOLD);
+
+       mkattr(DIALOG_TEXT, A_BOLD);
+       mkattr(DIALOG_BOX, A_BOLD);
+       mkattr(DIALOG_MENU_FORE, A_STANDOUT);
+       mkattr(DIALOG_MENU_BACK, A_NORMAL);
+
+       mkattr(INPUT_BOX, A_NORMAL);
+       mkattr(INPUT_HEADING, A_BOLD);
+       mkattr(INPUT_TEXT, A_NORMAL);
+       mkattr(INPUT_FIELD, A_UNDERLINE);
+
+       mkattr(FUNCTION_HIGHLIGHT, A_BOLD);
+       mkattr(FUNCTION_TEXT, A_REVERSE);
+}
+
+static void no_colors_theme(void)
+{
+       /* automatically add highlight, no color */
+#define mkattrn(name, attr) { attributes[name] = attr; }
+
+       mkattrn(NORMAL, NORMAL);
+       mkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE);
+
+       mkattrn(MAIN_MENU_FORE, A_STANDOUT);
+       mkattrn(MAIN_MENU_BACK, A_NORMAL);
+       mkattrn(MAIN_MENU_GREY, A_NORMAL);
+       mkattrn(MAIN_MENU_HEADING, A_BOLD);
+       mkattrn(MAIN_MENU_BOX, A_NORMAL);
+
+       mkattrn(SCROLLWIN_TEXT, A_NORMAL);
+       mkattrn(SCROLLWIN_HEADING, A_BOLD);
+       mkattrn(SCROLLWIN_BOX, A_BOLD);
+
+       mkattrn(DIALOG_TEXT, A_NORMAL);
+       mkattrn(DIALOG_BOX, A_BOLD);
+       mkattrn(DIALOG_MENU_FORE, A_STANDOUT);
+       mkattrn(DIALOG_MENU_BACK, A_NORMAL);
+
+       mkattrn(INPUT_BOX, A_BOLD);
+       mkattrn(INPUT_HEADING, A_BOLD);
+       mkattrn(INPUT_TEXT, A_NORMAL);
+       mkattrn(INPUT_FIELD, A_UNDERLINE);
+
+       mkattrn(FUNCTION_HIGHLIGHT, A_BOLD);
+       mkattrn(FUNCTION_TEXT, A_REVERSE);
+}
+
+void set_colors()
+{
+       start_color();
+       use_default_colors();
+       set_normal_colors();
+       if (has_colors()) {
+               normal_color_theme();
+       } else {
+               /* give deafults */
+               no_colors_theme();
+       }
+}
+
+
+/* this changes the windows attributes !!! */
+void print_in_middle(WINDOW *win,
+               int starty,
+               int startx,
+               int width,
+               const char *string,
+               chtype color)
+{      int length, x, y;
+       float temp;
+
+
+       if (win == NULL)
+               win = stdscr;
+       getyx(win, y, x);
+       if (startx != 0)
+               x = startx;
+       if (starty != 0)
+               y = starty;
+       if (width == 0)
+               width = 80;
+
+       length = strlen(string);
+       temp = (width - length) / 2;
+       x = startx + (int)temp;
+       wattrset(win, color);
+       mvwprintw(win, y, x, "%s", string);
+       refresh();
+}
+
+int get_line_no(const char *text)
+{
+       int i;
+       int total = 1;
+
+       if (!text)
+               return 0;
+
+       for (i = 0; text[i] != '\0'; i++)
+               if (text[i] == '\n')
+                       total++;
+       return total;
+}
+
+const char *get_line(const char *text, int line_no)
+{
+       int i;
+       int lines = 0;
+
+       if (!text)
+               return 0;
+
+       for (i = 0; text[i] != '\0' && lines < line_no; i++)
+               if (text[i] == '\n')
+                       lines++;
+       return text+i;
+}
+
+int get_line_length(const char *line)
+{
+       int res = 0;
+       while (*line != '\0' && *line != '\n') {
+               line++;
+               res++;
+       }
+       return res;
+}
+
+/* print all lines to the window. */
+void fill_window(WINDOW *win, const char *text)
+{
+       int x, y;
+       int total_lines = get_line_no(text);
+       int i;
+
+       getmaxyx(win, y, x);
+       /* do not go over end of line */
+       total_lines = min(total_lines, y);
+       for (i = 0; i < total_lines; i++) {
+               char tmp[x+10];
+               const char *line = get_line(text, i);
+               int len = get_line_length(line);
+               strncpy(tmp, line, min(len, x));
+               tmp[len] = '\0';
+               mvwprintw(win, i, 0, tmp);
+       }
+}
+
+/* get the message, and buttons.
+ * each button must be a char*
+ * return the selected button
+ *
+ * this dialog is used for 2 different things:
+ * 1) show a text box, no buttons.
+ * 2) show a dialog, with horizontal buttons
+ */
+int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
+{
+       va_list ap;
+       char *btn;
+       int btns_width = 0;
+       int msg_lines = 0;
+       int msg_width = 0;
+       int total_width;
+       int win_rows = 0;
+       WINDOW *win;
+       WINDOW *msg_win;
+       WINDOW *menu_win;
+       MENU *menu;
+       ITEM *btns[btn_num+1];
+       int i, x, y;
+       int res = -1;
+
+
+       va_start(ap, btn_num);
+       for (i = 0; i < btn_num; i++) {
+               btn = va_arg(ap, char *);
+               btns[i] = new_item(btn, "");
+               btns_width += strlen(btn)+1;
+       }
+       va_end(ap);
+       btns[btn_num] = NULL;
+
+       /* find the widest line of msg: */
+       msg_lines = get_line_no(msg);
+       for (i = 0; i < msg_lines; i++) {
+               const char *line = get_line(msg, i);
+               int len = get_line_length(line);
+               if (msg_width < len)
+                       msg_width = len;
+       }
+
+       total_width = max(msg_width, btns_width);
+       /* place dialog in middle of screen */
+       y = (LINES-(msg_lines+4))/2;
+       x = (COLS-(total_width+4))/2;
+
+
+       /* create the windows */
+       if (btn_num > 0)
+               win_rows = msg_lines+4;
+       else
+               win_rows = msg_lines+2;
+
+       win = newwin(win_rows, total_width+4, y, x);
+       keypad(win, TRUE);
+       menu_win = derwin(win, 1, btns_width, win_rows-2,
+                       1+(total_width+2-btns_width)/2);
+       menu = new_menu(btns);
+       msg_win = derwin(win, win_rows-2, msg_width, 1,
+                       1+(total_width+2-msg_width)/2);
+
+       set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
+       set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
+
+       wattrset(win, attributes[DIALOG_BOX]);
+       box(win, 0, 0);
+
+       /* print message */
+       wattrset(msg_win, attributes[DIALOG_TEXT]);
+       fill_window(msg_win, msg);
+
+       set_menu_win(menu, win);
+       set_menu_sub(menu, menu_win);
+       set_menu_format(menu, 1, btn_num);
+       menu_opts_off(menu, O_SHOWDESC);
+       menu_opts_off(menu, O_SHOWMATCH);
+       menu_opts_on(menu, O_ONEVALUE);
+       menu_opts_on(menu, O_NONCYCLIC);
+       set_menu_mark(menu, "");
+       post_menu(menu);
+
+
+       touchwin(win);
+       refresh_all_windows(main_window);
+       while ((res = wgetch(win))) {
+               switch (res) {
+               case KEY_LEFT:
+                       menu_driver(menu, REQ_LEFT_ITEM);
+                       break;
+               case KEY_RIGHT:
+                       menu_driver(menu, REQ_RIGHT_ITEM);
+                       break;
+               case 10: /* ENTER */
+               case 27: /* ESCAPE */
+               case ' ':
+               case KEY_F(F_BACK):
+               case KEY_F(F_EXIT):
+                       break;
+               }
+               touchwin(win);
+               refresh_all_windows(main_window);
+
+               if (res == 10 || res == ' ') {
+                       res = item_index(current_item(menu));
+                       break;
+               } else if (res == 27 || res == KEY_F(F_BACK) ||
+                               res == KEY_F(F_EXIT)) {
+                       res = KEY_EXIT;
+                       break;
+               }
+       }
+
+       unpost_menu(menu);
+       free_menu(menu);
+       for (i = 0; i < btn_num; i++)
+               free_item(btns[i]);
+
+       delwin(win);
+       return res;
+}
+
+int dialog_inputbox(WINDOW *main_window,
+               const char *title, const char *prompt,
+               const char *init, char *result, int result_len)
+{
+       int prompt_lines = 0;
+       int prompt_width = 0;
+       WINDOW *win;
+       WINDOW *prompt_win;
+       WINDOW *form_win;
+       PANEL *panel;
+       int i, x, y;
+       int res = -1;
+       int cursor_position = strlen(init);
+
+
+       /* find the widest line of msg: */
+       prompt_lines = get_line_no(prompt);
+       for (i = 0; i < prompt_lines; i++) {
+               const char *line = get_line(prompt, i);
+               int len = get_line_length(line);
+               prompt_width = max(prompt_width, len);
+       }
+
+       if (title)
+               prompt_width = max(prompt_width, strlen(title));
+
+       /* place dialog in middle of screen */
+       y = (LINES-(prompt_lines+4))/2;
+       x = (COLS-(prompt_width+4))/2;
+
+       strncpy(result, init, result_len);
+
+       /* create the windows */
+       win = newwin(prompt_lines+6, prompt_width+7, y, x);
+       prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
+       form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
+       keypad(form_win, TRUE);
+
+       wattrset(form_win, attributes[INPUT_FIELD]);
+
+       wattrset(win, attributes[INPUT_BOX]);
+       box(win, 0, 0);
+       wattrset(win, attributes[INPUT_HEADING]);
+       if (title)
+               mvwprintw(win, 0, 3, "%s", title);
+
+       /* print message */
+       wattrset(prompt_win, attributes[INPUT_TEXT]);
+       fill_window(prompt_win, prompt);
+
+       mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
+       mvwprintw(form_win, 0, 0, "%s", result);
+
+       /* create panels */
+       panel = new_panel(win);
+
+       /* show the cursor */
+       curs_set(1);
+
+       touchwin(win);
+       refresh_all_windows(main_window);
+       while ((res = wgetch(form_win))) {
+               int len = strlen(result);
+               switch (res) {
+               case 10: /* ENTER */
+               case 27: /* ESCAPE */
+               case KEY_F(F_HELP):
+               case KEY_F(F_EXIT):
+               case KEY_F(F_BACK):
+                       break;
+               case 127:
+               case KEY_BACKSPACE:
+                       if (cursor_position > 0) {
+                               memmove(&result[cursor_position-1],
+                                               &result[cursor_position],
+                                               len-cursor_position+1);
+                               cursor_position--;
+                       }
+                       break;
+               case KEY_DC:
+                       if (cursor_position >= 0 && cursor_position < len) {
+                               memmove(&result[cursor_position],
+                                               &result[cursor_position+1],
+                                               len-cursor_position+1);
+                       }
+                       break;
+               case KEY_UP:
+               case KEY_RIGHT:
+                       if (cursor_position < len &&
+                           cursor_position < min(result_len, prompt_width))
+                               cursor_position++;
+                       break;
+               case KEY_DOWN:
+               case KEY_LEFT:
+                       if (cursor_position > 0)
+                               cursor_position--;
+                       break;
+               default:
+                       if ((isgraph(res) || isspace(res)) &&
+                                       len-2 < result_len) {
+                               /* insert the char at the proper position */
+                               memmove(&result[cursor_position+1],
+                                               &result[cursor_position],
+                                               len+1);
+                               result[cursor_position] = res;
+                               cursor_position++;
+                       } else {
+                               mvprintw(0, 0, "unknow key: %d\n", res);
+                       }
+                       break;
+               }
+               wmove(form_win, 0, 0);
+               wclrtoeol(form_win);
+               mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
+               mvwprintw(form_win, 0, 0, "%s", result);
+               wmove(form_win, 0, cursor_position);
+               touchwin(win);
+               refresh_all_windows(main_window);
+
+               if (res == 10) {
+                       res = 0;
+                       break;
+               } else if (res == 27 || res == KEY_F(F_BACK) ||
+                               res == KEY_F(F_EXIT)) {
+                       res = KEY_EXIT;
+                       break;
+               } else if (res == KEY_F(F_HELP)) {
+                       res = 1;
+                       break;
+               }
+       }
+
+       /* hide the cursor */
+       curs_set(0);
+       del_panel(panel);
+       delwin(prompt_win);
+       delwin(form_win);
+       delwin(win);
+       return res;
+}
+
+/* refresh all windows in the correct order */
+void refresh_all_windows(WINDOW *main_window)
+{
+       update_panels();
+       touchwin(main_window);
+       refresh();
+}
+
+/* layman's scrollable window... */
+void show_scroll_win(WINDOW *main_window,
+               const char *title,
+               const char *text)
+{
+       int res;
+       int total_lines = get_line_no(text);
+       int x, y;
+       int start_x = 0, start_y = 0;
+       int text_lines = 0, text_cols = 0;
+       int total_cols = 0;
+       int win_cols = 0;
+       int win_lines = 0;
+       int i = 0;
+       WINDOW *win;
+       WINDOW *pad;
+       PANEL *panel;
+
+       /* find the widest line of msg: */
+       total_lines = get_line_no(text);
+       for (i = 0; i < total_lines; i++) {
+               const char *line = get_line(text, i);
+               int len = get_line_length(line);
+               total_cols = max(total_cols, len+2);
+       }
+
+       /* create the pad */
+       pad = newpad(total_lines+10, total_cols+10);
+       wattrset(pad, attributes[SCROLLWIN_TEXT]);
+       fill_window(pad, text);
+
+       win_lines = min(total_lines+4, LINES-2);
+       win_cols = min(total_cols+2, COLS-2);
+       text_lines = max(win_lines-4, 0);
+       text_cols = max(win_cols-2, 0);
+
+       /* place window in middle of screen */
+       y = (LINES-win_lines)/2;
+       x = (COLS-win_cols)/2;
+
+       win = newwin(win_lines, win_cols, y, x);
+       keypad(win, TRUE);
+       /* show the help in the help window, and show the help panel */
+       wattrset(win, attributes[SCROLLWIN_BOX]);
+       box(win, 0, 0);
+       wattrset(win, attributes[SCROLLWIN_HEADING]);
+       mvwprintw(win, 0, 3, " %s ", title);
+       panel = new_panel(win);
+
+       /* handle scrolling */
+       do {
+
+               copywin(pad, win, start_y, start_x, 2, 2, text_lines,
+                               text_cols, 0);
+               print_in_middle(win,
+                               text_lines+2,
+                               0,
+                               text_cols,
+                               "<OK>",
+                               attributes[DIALOG_MENU_FORE]);
+               wrefresh(win);
+
+               res = wgetch(win);
+               switch (res) {
+               case KEY_NPAGE:
+               case ' ':
+                       start_y += text_lines-2;
+                       break;
+               case KEY_PPAGE:
+                       start_y -= text_lines+2;
+                       break;
+               case KEY_HOME:
+                       start_y = 0;
+                       break;
+               case KEY_END:
+                       start_y = total_lines-text_lines;
+                       break;
+               case KEY_DOWN:
+               case 'j':
+                       start_y++;
+                       break;
+               case KEY_UP:
+               case 'k':
+                       start_y--;
+                       break;
+               case KEY_LEFT:
+               case 'h':
+                       start_x--;
+                       break;
+               case KEY_RIGHT:
+               case 'l':
+                       start_x++;
+                       break;
+               }
+               if (res == 10 || res == 27 || res == 'q'
+                   || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) {
+                       break;
+               }
+               if (start_y < 0)
+                       start_y = 0;
+               if (start_y >= total_lines-text_lines)
+                       start_y = total_lines-text_lines;
+               if (start_x < 0)
+                       start_x = 0;
+               if (start_x >= total_cols-text_cols)
+                       start_x = total_cols-text_cols;
+       } while (res);
+
+       del_panel(panel);
+       delwin(win);
+       refresh_all_windows(main_window);
+}
diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h
new file mode 100644 (file)
index 0000000..fb42966
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <locale.h>
+#include <curses.h>
+#include <menu.h>
+#include <panel.h>
+#include <form.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "ncurses.h"
+
+#define max(a, b) ({\
+               typeof(a) _a = a;\
+               typeof(b) _b = b;\
+               _a > _b ? _a : _b; })
+
+#define min(a, b) ({\
+               typeof(a) _a = a;\
+               typeof(b) _b = b;\
+               _a < _b ? _a : _b; })
+
+typedef enum {
+       NORMAL = 1,
+       MAIN_HEADING,
+       MAIN_MENU_BOX,
+       MAIN_MENU_FORE,
+       MAIN_MENU_BACK,
+       MAIN_MENU_GREY,
+       MAIN_MENU_HEADING,
+       SCROLLWIN_TEXT,
+       SCROLLWIN_HEADING,
+       SCROLLWIN_BOX,
+       DIALOG_TEXT,
+       DIALOG_MENU_FORE,
+       DIALOG_MENU_BACK,
+       DIALOG_BOX,
+       INPUT_BOX,
+       INPUT_HEADING,
+       INPUT_TEXT,
+       INPUT_FIELD,
+       FUNCTION_TEXT,
+       FUNCTION_HIGHLIGHT,
+       ATTR_MAX
+} attributes_t;
+extern attributes_t attributes[];
+
+typedef enum {
+       F_HELP = 1,
+       F_SYMBOL = 2,
+       F_INSTS = 3,
+       F_CONF = 4,
+       F_BACK = 5,
+       F_SAVE = 6,
+       F_LOAD = 7,
+       F_EXIT = 8
+} function_key;
+
+void set_colors(void);
+
+/* this changes the windows attributes !!! */
+void print_in_middle(WINDOW *win,
+               int starty,
+               int startx,
+               int width,
+               const char *string,
+               chtype color);
+int get_line_length(const char *line);
+int get_line_no(const char *text);
+const char *get_line(const char *text, int line_no);
+void fill_window(WINDOW *win, const char *text);
+int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...);
+int dialog_inputbox(WINDOW *main_window,
+               const char *title, const char *prompt,
+               const char *init, char *result, int result_len);
+void refresh_all_windows(WINDOW *main_window);
+void show_scroll_win(WINDOW *main_window,
+               const char *title,
+               const char *text);
index 6c8fbbb66ebcaddefff183696d1c5d89bc2d6c09..2e7a048e0cfceb32970d4d0a6fa8b211d70ef83e 100644 (file)
@@ -651,12 +651,20 @@ bool sym_is_changable(struct symbol *sym)
        return sym->visible > sym->rev_dep.tri;
 }
 
+static unsigned strhash(const char *s)
+{
+       /* fnv32 hash */
+       unsigned hash = 2166136261U;
+       for (; *s; s++)
+               hash = (hash ^ *s) * 0x01000193;
+       return hash;
+}
+
 struct symbol *sym_lookup(const char *name, int flags)
 {
        struct symbol *symbol;
-       const char *ptr;
        char *new_name;
-       int hash = 0;
+       int hash;
 
        if (name) {
                if (name[0] && !name[1]) {
@@ -666,12 +674,11 @@ struct symbol *sym_lookup(const char *name, int flags)
                        case 'n': return &symbol_no;
                        }
                }
-               for (ptr = name; *ptr; ptr++)
-                       hash += *ptr;
-               hash &= 0xff;
+               hash = strhash(name) % SYMBOL_HASHSIZE;
 
                for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
-                       if (!strcmp(symbol->name, name) &&
+                       if (symbol->name &&
+                           !strcmp(symbol->name, name) &&
                            (flags ? symbol->flags & flags
                                   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
                                return symbol;
@@ -679,7 +686,7 @@ struct symbol *sym_lookup(const char *name, int flags)
                new_name = strdup(name);
        } else {
                new_name = NULL;
-               hash = 256;
+               hash = 0;
        }
 
        symbol = malloc(sizeof(*symbol));
@@ -697,7 +704,6 @@ struct symbol *sym_lookup(const char *name, int flags)
 struct symbol *sym_find(const char *name)
 {
        struct symbol *symbol = NULL;
-       const char *ptr;
        int hash = 0;
 
        if (!name)
@@ -710,12 +716,11 @@ struct symbol *sym_find(const char *name)
                case 'n': return &symbol_no;
                }
        }
-       for (ptr = name; *ptr; ptr++)
-               hash += *ptr;
-       hash &= 0xff;
+       hash = strhash(name) % SYMBOL_HASHSIZE;
 
        for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
-               if (!strcmp(symbol->name, name) &&
+               if (symbol->name &&
+                   !strcmp(symbol->name, name) &&
                    !(symbol->flags & SYMBOL_CONST))
                                break;
        }
@@ -750,6 +755,7 @@ struct symbol **sym_re_search(const char *pattern)
                                return NULL;
                        }
                }
+               sym_calc_value(sym);
                sym_arr[cnt++] = sym;
        }
        if (sym_arr)
index 25d1ec4ca28a0e5ed3090291df8f2f67e2a20b4b..78b5c04e736bcfad3f25d7f85fe2b5660572cb52 100644 (file)
@@ -78,6 +78,7 @@ struct gstr str_new(void)
        struct gstr gs;
        gs.s = malloc(sizeof(char) * 64);
        gs.len = 64;
+       gs.max_width = 0;
        strcpy(gs.s, "\0");
        return gs;
 }
@@ -88,6 +89,7 @@ struct gstr str_assign(const char *s)
        struct gstr gs;
        gs.s = strdup(s);
        gs.len = strlen(s) + 1;
+       gs.max_width = 0;
        return gs;
 }
 
index 6e9dcd59aa87c5cc53378b9a789aad92fdf1d5f6..32a9eefd842cb132322045ec45d360abdd3b141a 100644 (file)
@@ -104,7 +104,7 @@ static void zconf_error(const char *err, ...);
 static void zconferror(const char *err);
 static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
 
-struct symbol *symbol_hash[257];
+struct symbol *symbol_hash[SYMBOL_HASHSIZE];
 
 static struct menu *current_menu, *current_entry;
 
@@ -2220,7 +2220,7 @@ void conf_parse(const char *name)
        zconf_initscan(name);
 
        sym_init();
-       menu_init();
+       _menu_init();
        modules_sym = sym_lookup(NULL, 0);
        modules_sym->type = S_BOOLEAN;
        modules_sym->flags |= SYMBOL_AUTO;
@@ -2336,9 +2336,9 @@ static void print_symbol(FILE *out, struct menu *menu)
        struct property *prop;
 
        if (sym_is_choice(sym))
-               fprintf(out, "choice\n");
+               fprintf(out, "\nchoice\n");
        else
-               fprintf(out, "config %s\n", sym->name);
+               fprintf(out, "\nconfig %s\n", sym->name);
        switch (sym->type) {
        case S_BOOLEAN:
                fputs("  boolean\n", out);
@@ -2384,6 +2384,21 @@ static void print_symbol(FILE *out, struct menu *menu)
                case P_CHOICE:
                        fputs("  #choice value\n", out);
                        break;
+               case P_SELECT:
+                       fputs( "  select ", out);
+                       expr_fprint(prop->expr, out);
+                       fputc('\n', out);
+                       break;
+               case P_RANGE:
+                       fputs( "  range ", out);
+                       expr_fprint(prop->expr, out);
+                       fputc('\n', out);
+                       break;
+               case P_MENU:
+                       fputs( "  menu ", out);
+                       print_quoted_string(out, prop->text);
+                       fputc('\n', out);
+                       break;
                default:
                        fprintf(out, "  unknown prop %d!\n", prop->type);
                        break;
@@ -2395,7 +2410,6 @@ static void print_symbol(FILE *out, struct menu *menu)
                        menu->help[len] = 0;
                fprintf(out, "  help\n%s\n", menu->help);
        }
-       fputc('\n', out);
 }
 
 void zconfdump(FILE *out)
@@ -2428,7 +2442,6 @@ void zconfdump(FILE *out)
                                expr_fprint(prop->visible.expr, out);
                                fputc('\n', out);
                        }
-                       fputs("\n", out);
                }
 
                if (menu->list)
index 8c43491f8cc9635cde61b9f80a98598a77948d75..23dfd3baa7a1ba906c80a0df0383fbfcf8979bad 100644 (file)
@@ -27,7 +27,7 @@ static void zconf_error(const char *err, ...);
 static void zconferror(const char *err);
 static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
 
-struct symbol *symbol_hash[257];
+struct symbol *symbol_hash[SYMBOL_HASHSIZE];
 
 static struct menu *current_menu, *current_entry;
 
@@ -475,7 +475,7 @@ void conf_parse(const char *name)
        zconf_initscan(name);
 
        sym_init();
-       menu_init();
+       _menu_init();
        modules_sym = sym_lookup(NULL, 0);
        modules_sym->type = S_BOOLEAN;
        modules_sym->flags |= SYMBOL_AUTO;
@@ -591,9 +591,9 @@ static void print_symbol(FILE *out, struct menu *menu)
        struct property *prop;
 
        if (sym_is_choice(sym))
-               fprintf(out, "choice\n");
+               fprintf(out, "\nchoice\n");
        else
-               fprintf(out, "config %s\n", sym->name);
+               fprintf(out, "\nconfig %s\n", sym->name);
        switch (sym->type) {
        case S_BOOLEAN:
                fputs("  boolean\n", out);
@@ -639,6 +639,21 @@ static void print_symbol(FILE *out, struct menu *menu)
                case P_CHOICE:
                        fputs("  #choice value\n", out);
                        break;
+               case P_SELECT:
+                       fputs( "  select ", out);
+                       expr_fprint(prop->expr, out);
+                       fputc('\n', out);
+                       break;
+               case P_RANGE:
+                       fputs( "  range ", out);
+                       expr_fprint(prop->expr, out);
+                       fputc('\n', out);
+                       break;
+               case P_MENU:
+                       fputs( "  menu ", out);
+                       print_quoted_string(out, prop->text);
+                       fputc('\n', out);
+                       break;
                default:
                        fprintf(out, "  unknown prop %d!\n", prop->type);
                        break;
@@ -650,7 +665,6 @@ static void print_symbol(FILE *out, struct menu *menu)
                        menu->help[len] = 0;
                fprintf(out, "  help\n%s\n", menu->help);
        }
-       fputc('\n', out);
 }
 
 void zconfdump(FILE *out)
@@ -683,7 +697,6 @@ void zconfdump(FILE *out)
                                expr_fprint(prop->visible.expr, out);
                                fputc('\n', out);
                        }
-                       fputs("\n", out);
                }
 
                if (menu->list)
index e950f9cde0199194f8db3e0ceb4579178f186bbe..827896f56501aaebba885e70adc24a477fd31884 100644 (file)
@@ -2,6 +2,7 @@
 
 use File::Basename;
 use Math::BigInt;
+use Getopt::Long;
 
 # Copyright 2008, Intel Corporation
 #
@@ -15,6 +16,16 @@ use Math::BigInt;
 #      Arjan van de Ven <arjan@linux.intel.com>
 
 
+my $cross_compile = "";
+my $vmlinux_name = "";
+my $modulefile = "";
+
+# Get options
+Getopt::Long::GetOptions(
+       'cross-compile|c=s'     => \$cross_compile,
+       'module|m=s'            => \$modulefile,
+       'help|h'                => \&usage,
+) || usage ();
 my $vmlinux_name = $ARGV[0];
 if (!defined($vmlinux_name)) {
        my $kerver = `uname -r`;
@@ -23,9 +34,8 @@ if (!defined($vmlinux_name)) {
        print "No vmlinux specified, assuming $vmlinux_name\n";
 }
 my $filename = $vmlinux_name;
-#
-# Step 1: Parse the oops to find the EIP value
-#
+
+# Parse the oops to find the EIP value
 
 my $target = "0";
 my $function;
@@ -177,26 +187,26 @@ my $decodestart = Math::BigInt->from_hex("0x$target") - Math::BigInt->from_hex("
 my $decodestop = Math::BigInt->from_hex("0x$target") + 8192;
 if ($target eq "0") {
        print "No oops found!\n";
-       print "Usage: \n";
-       print "    dmesg | perl scripts/markup_oops.pl vmlinux\n";
-       exit;
+       usage();
 }
 
 # if it's a module, we need to find the .ko file and calculate a load offset
 if ($module ne "") {
-       my $modulefile = `modinfo $module | grep '^filename:' | awk '{ print \$2 }'`;
-       chomp($modulefile);
+       if ($modulefile eq "") {
+               $modulefile = `modinfo -F filename $module`;
+               chomp($modulefile);
+       }
        $filename = $modulefile;
        if ($filename eq "") {
                print "Module .ko file for $module not found. Aborting\n";
                exit;
        }
        # ok so we found the module, now we need to calculate the vma offset
-       open(FILE, "objdump -dS $filename |") || die "Cannot start objdump";
+       open(FILE, $cross_compile."objdump -dS $filename |") || die "Cannot start objdump";
        while (<FILE>) {
                if ($_ =~ /^([0-9a-f]+) \<$function\>\:/) {
                        my $fu = $1;
-                       $vmaoffset = hex($target) - hex($fu) - hex($func_offset);
+                       $vmaoffset = Math::BigInt->from_hex("0x$target") - Math::BigInt->from_hex("0x$fu") - Math::BigInt->from_hex("0x$func_offset");
                }
        }
        close(FILE);
@@ -204,7 +214,7 @@ if ($module ne "") {
 
 my $counter = 0;
 my $state   = 0;
-my $center  = 0;
+my $center  = -1;
 my @lines;
 my @reglines;
 
@@ -212,7 +222,7 @@ sub InRange {
        my ($address, $target) = @_;
        my $ad = "0x".$address;
        my $ta = "0x".$target;
-       my $delta = hex($ad) - hex($ta);
+       my $delta = Math::BigInt->from_hex($ad) - Math::BigInt->from_hex($ta);
 
        if (($delta > -4096) && ($delta < 4096)) {
                return 1;
@@ -225,7 +235,7 @@ sub InRange {
 # first, parse the input into the lines array, but to keep size down,
 # we only do this for 4Kb around the sweet spot
 
-open(FILE, "objdump -dS --adjust-vma=$vmaoffset --start-address=$decodestart --stop-address=$decodestop $filename |") || die "Cannot start objdump";
+open(FILE, $cross_compile."objdump -dS --adjust-vma=$vmaoffset --start-address=$decodestart --stop-address=$decodestop $filename |") || die "Cannot start objdump";
 
 while (<FILE>) {
        my $line = $_;
@@ -236,7 +246,8 @@ while (<FILE>) {
                                $state = 1;
                        }
                }
-       } else {
+       }
+       if ($state == 1) {
                if ($line =~ /^([a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]+)\:/) {
                        my $val = $1;
                        if (!InRange($val, $target)) {
@@ -259,7 +270,7 @@ if ($counter == 0) {
        exit;
 }
 
-if ($center == 0) {
+if ($center == -1) {
        print "No matching code found \n";
        exit;
 }
@@ -344,3 +355,16 @@ while ($i < $finish) {
        $i = $i +1;
 }
 
+sub usage {
+       print <<EOT;
+Usage:
+  dmesg | perl $0 [OPTION] [VMLINUX]
+
+OPTION:
+  -c, --cross-compile CROSS_COMPILE    Specify the prefix used for toolchain.
+  -m, --module MODULE_DIRNAME          Specify the module filename.
+  -h, --help                           Help.
+EOT
+       exit;
+}
+
index 23dbad80cce9e16ce885d61163a5f79c1ca2b981..50ad317a4bf9b41bc62d074ee8bd19a9864ffda6 100755 (executable)
@@ -67,9 +67,8 @@ UTS_TRUNCATE="cut -b -$UTS_LEN"
   echo \#define LINUX_COMPILE_BY \"`whoami`\"
   echo \#define LINUX_COMPILE_HOST \"`hostname | $UTS_TRUNCATE`\"
 
-  if [ -x /bin/dnsdomainname ]; then
-    domain=`dnsdomainname 2> /dev/null`
-  elif [ -x /bin/domainname ]; then
+  domain=`dnsdomainname 2> /dev/null`
+  if [ -z "$domain" ]; then
     domain=`domainname 2> /dev/null`
   fi
 
index 20923613467cf376db195e17a9df754e934ab470..f8779006986d16a2e39341a7aa66ebf7b8825162 100644 (file)
@@ -781,10 +781,13 @@ static void check_section(const char *modname, struct elf_info *elf,
 #define ALL_EXIT_TEXT_SECTIONS \
        ".exit.text$", ".devexit.text$", ".cpuexit.text$", ".memexit.text$"
 
-#define ALL_INIT_SECTIONS INIT_SECTIONS, DEV_INIT_SECTIONS, \
-       CPU_INIT_SECTIONS, MEM_INIT_SECTIONS
-#define ALL_EXIT_SECTIONS EXIT_SECTIONS, DEV_EXIT_SECTIONS, \
-       CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS
+#define ALL_XXXINIT_SECTIONS DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, \
+       MEM_INIT_SECTIONS
+#define ALL_XXXEXIT_SECTIONS DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, \
+       MEM_EXIT_SECTIONS
+
+#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS
+#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS
 
 #define DATA_SECTIONS ".data$", ".data.rel$"
 #define TEXT_SECTIONS ".text$"
@@ -814,33 +817,29 @@ static const char *data_sections[] = { DATA_SECTIONS, NULL };
 
 
 /* symbols in .data that may refer to init/exit sections */
-static const char *symbol_white_list[] =
-{
-       "*driver",
-       "*_template", /* scsi uses *_template a lot */
-       "*_timer",    /* arm uses ops structures named _timer a lot */
-       "*_sht",      /* scsi also used *_sht to some extent */
-       "*_ops",
-       "*_probe",
-       "*_probe_one",
-       "*_console",
-       NULL
-};
+#define DEFAULT_SYMBOL_WHITE_LIST                                      \
+       "*driver",                                                      \
+       "*_template", /* scsi uses *_template a lot */                  \
+       "*_timer",    /* arm uses ops structures named _timer a lot */  \
+       "*_sht",      /* scsi also used *_sht to some extent */         \
+       "*_ops",                                                        \
+       "*_probe",                                                      \
+       "*_probe_one",                                                  \
+       "*_console"
 
 static const char *head_sections[] = { ".head.text*", NULL };
 static const char *linker_symbols[] =
        { "__init_begin", "_sinittext", "_einittext", NULL };
 
 enum mismatch {
-       NO_MISMATCH,
-       TEXT_TO_INIT,
-       DATA_TO_INIT,
-       TEXT_TO_EXIT,
-       DATA_TO_EXIT,
-       XXXINIT_TO_INIT,
-       XXXEXIT_TO_EXIT,
-       INIT_TO_EXIT,
-       EXIT_TO_INIT,
+       TEXT_TO_ANY_INIT,
+       DATA_TO_ANY_INIT,
+       TEXT_TO_ANY_EXIT,
+       DATA_TO_ANY_EXIT,
+       XXXINIT_TO_SOME_INIT,
+       XXXEXIT_TO_SOME_EXIT,
+       ANY_INIT_TO_ANY_EXIT,
+       ANY_EXIT_TO_ANY_INIT,
        EXPORT_TO_INIT_EXIT,
 };
 
@@ -848,6 +847,7 @@ struct sectioncheck {
        const char *fromsec[20];
        const char *tosec[20];
        enum mismatch mismatch;
+       const char *symbol_white_list[20];
 };
 
 const struct sectioncheck sectioncheck[] = {
@@ -857,80 +857,103 @@ const struct sectioncheck sectioncheck[] = {
 {
        .fromsec = { TEXT_SECTIONS, NULL },
        .tosec   = { ALL_INIT_SECTIONS, NULL },
-       .mismatch = TEXT_TO_INIT,
+       .mismatch = TEXT_TO_ANY_INIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 {
        .fromsec = { DATA_SECTIONS, NULL },
-       .tosec   = { ALL_INIT_SECTIONS, NULL },
-       .mismatch = DATA_TO_INIT,
+       .tosec   = { ALL_XXXINIT_SECTIONS, NULL },
+       .mismatch = DATA_TO_ANY_INIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+{
+       .fromsec = { DATA_SECTIONS, NULL },
+       .tosec   = { INIT_SECTIONS, NULL },
+       .mismatch = DATA_TO_ANY_INIT,
+       .symbol_white_list = {
+               "*_template", "*_timer", "*_sht", "*_ops",
+               "*_probe", "*_probe_one", "*_console", NULL
+       },
 },
 {
        .fromsec = { TEXT_SECTIONS, NULL },
        .tosec   = { ALL_EXIT_SECTIONS, NULL },
-       .mismatch = TEXT_TO_EXIT,
+       .mismatch = TEXT_TO_ANY_EXIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 {
        .fromsec = { DATA_SECTIONS, NULL },
        .tosec   = { ALL_EXIT_SECTIONS, NULL },
-       .mismatch = DATA_TO_EXIT,
+       .mismatch = DATA_TO_ANY_EXIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not reference init code/data from devinit/cpuinit/meminit code/data */
 {
-       .fromsec = { DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, MEM_INIT_SECTIONS, NULL },
+       .fromsec = { ALL_XXXINIT_SECTIONS, NULL },
        .tosec   = { INIT_SECTIONS, NULL },
-       .mismatch = XXXINIT_TO_INIT,
+       .mismatch = XXXINIT_TO_SOME_INIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not reference cpuinit code/data from meminit code/data */
 {
        .fromsec = { MEM_INIT_SECTIONS, NULL },
        .tosec   = { CPU_INIT_SECTIONS, NULL },
-       .mismatch = XXXINIT_TO_INIT,
+       .mismatch = XXXINIT_TO_SOME_INIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not reference meminit code/data from cpuinit code/data */
 {
        .fromsec = { CPU_INIT_SECTIONS, NULL },
        .tosec   = { MEM_INIT_SECTIONS, NULL },
-       .mismatch = XXXINIT_TO_INIT,
+       .mismatch = XXXINIT_TO_SOME_INIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not reference exit code/data from devexit/cpuexit/memexit code/data */
 {
-       .fromsec = { DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS, NULL },
+       .fromsec = { ALL_XXXEXIT_SECTIONS, NULL },
        .tosec   = { EXIT_SECTIONS, NULL },
-       .mismatch = XXXEXIT_TO_EXIT,
+       .mismatch = XXXEXIT_TO_SOME_EXIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not reference cpuexit code/data from memexit code/data */
 {
        .fromsec = { MEM_EXIT_SECTIONS, NULL },
        .tosec   = { CPU_EXIT_SECTIONS, NULL },
-       .mismatch = XXXEXIT_TO_EXIT,
+       .mismatch = XXXEXIT_TO_SOME_EXIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not reference memexit code/data from cpuexit code/data */
 {
        .fromsec = { CPU_EXIT_SECTIONS, NULL },
        .tosec   = { MEM_EXIT_SECTIONS, NULL },
-       .mismatch = XXXEXIT_TO_EXIT,
+       .mismatch = XXXEXIT_TO_SOME_EXIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not use exit code/data from init code */
 {
        .fromsec = { ALL_INIT_SECTIONS, NULL },
        .tosec   = { ALL_EXIT_SECTIONS, NULL },
-       .mismatch = INIT_TO_EXIT,
+       .mismatch = ANY_INIT_TO_ANY_EXIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not use init code/data from exit code */
 {
        .fromsec = { ALL_EXIT_SECTIONS, NULL },
        .tosec   = { ALL_INIT_SECTIONS, NULL },
-       .mismatch = EXIT_TO_INIT,
+       .mismatch = ANY_EXIT_TO_ANY_INIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not export init/exit functions or data */
 {
        .fromsec = { "__ksymtab*", NULL },
        .tosec   = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
-       .mismatch = EXPORT_TO_INIT_EXIT
+       .mismatch = EXPORT_TO_INIT_EXIT,
+       .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 }
 };
 
-static int section_mismatch(const char *fromsec, const char *tosec)
+static const struct sectioncheck *section_mismatch(
+               const char *fromsec, const char *tosec)
 {
        int i;
        int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck);
@@ -939,10 +962,10 @@ static int section_mismatch(const char *fromsec, const char *tosec)
        for (i = 0; i < elems; i++) {
                if (match(fromsec, check->fromsec) &&
                    match(tosec, check->tosec))
-                       return check->mismatch;
+                       return check;
                check++;
        }
-       return NO_MISMATCH;
+       return NULL;
 }
 
 /**
@@ -961,7 +984,7 @@ static int section_mismatch(const char *fromsec, const char *tosec)
  * Pattern 2:
  *   Many drivers utilise a *driver container with references to
  *   add, remove, probe functions etc.
- *   These functions may often be marked __init and we do not want to
+ *   These functions may often be marked __devinit and we do not want to
  *   warn here.
  *   the pattern is identified by:
  *   tosec   = init or exit section
@@ -982,7 +1005,8 @@ static int section_mismatch(const char *fromsec, const char *tosec)
  *   refsymname = __init_begin, _sinittext, _einittext
  *
  **/
-static int secref_whitelist(const char *fromsec, const char *fromsym,
+static int secref_whitelist(const struct sectioncheck *mismatch,
+                           const char *fromsec, const char *fromsym,
                            const char *tosec, const char *tosym)
 {
        /* Check for pattern 1 */
@@ -994,7 +1018,7 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,
        /* Check for pattern 2 */
        if (match(tosec, init_exit_sections) &&
            match(fromsec, data_sections) &&
-           match(fromsym, symbol_white_list))
+           match(fromsym, mismatch->symbol_white_list))
                return 0;
 
        /* Check for pattern 3 */
@@ -1155,7 +1179,8 @@ static int is_function(Elf_Sym *sym)
  * Try to find symbols near it so user can find it.
  * Check whitelist before warning - it may be a false positive.
  */
-static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
+static void report_sec_mismatch(const char *modname,
+                               const struct sectioncheck *mismatch,
                                 const char *fromsec,
                                 unsigned long long fromaddr,
                                 const char *fromsym,
@@ -1186,8 +1211,8 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
             modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec,
             tosym, to_p);
 
-       switch (mismatch) {
-       case TEXT_TO_INIT:
+       switch (mismatch->mismatch) {
+       case TEXT_TO_ANY_INIT:
                fprintf(stderr,
                "The function %s%s() references\n"
                "the %s %s%s%s.\n"
@@ -1197,8 +1222,8 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
                to, sec2annotation(tosec), tosym, to_p,
                fromsym, sec2annotation(tosec), tosym);
                break;
-       case DATA_TO_INIT: {
-               const char **s = symbol_white_list;
+       case DATA_TO_ANY_INIT: {
+               const char *const *s = mismatch->symbol_white_list;
                fprintf(stderr,
                "The variable %s references\n"
                "the %s %s%s%s\n"
@@ -1211,15 +1236,15 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
                fprintf(stderr, "\n");
                break;
        }
-       case TEXT_TO_EXIT:
+       case TEXT_TO_ANY_EXIT:
                fprintf(stderr,
                "The function %s() references a %s in an exit section.\n"
                "Often the %s %s%s has valid usage outside the exit section\n"
                "and the fix is to remove the %sannotation of %s.\n",
                fromsym, to, to, tosym, to_p, sec2annotation(tosec), tosym);
                break;
-       case DATA_TO_EXIT: {
-               const char **s = symbol_white_list;
+       case DATA_TO_ANY_EXIT: {
+               const char *const *s = mismatch->symbol_white_list;
                fprintf(stderr,
                "The variable %s references\n"
                "the %s %s%s%s\n"
@@ -1232,8 +1257,8 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
                fprintf(stderr, "\n");
                break;
        }
-       case XXXINIT_TO_INIT:
-       case XXXEXIT_TO_EXIT:
+       case XXXINIT_TO_SOME_INIT:
+       case XXXEXIT_TO_SOME_EXIT:
                fprintf(stderr,
                "The %s %s%s%s references\n"
                "a %s %s%s%s.\n"
@@ -1243,7 +1268,7 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
                to, sec2annotation(tosec), tosym, to_p,
                tosym, fromsym, tosym);
                break;
-       case INIT_TO_EXIT:
+       case ANY_INIT_TO_ANY_EXIT:
                fprintf(stderr,
                "The %s %s%s%s references\n"
                "a %s %s%s%s.\n"
@@ -1256,7 +1281,7 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
                to, sec2annotation(tosec), tosym, to_p,
                sec2annotation(tosec), tosym, to_p);
                break;
-       case EXIT_TO_INIT:
+       case ANY_EXIT_TO_ANY_INIT:
                fprintf(stderr,
                "The %s %s%s%s references\n"
                "a %s %s%s%s.\n"
@@ -1275,8 +1300,6 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
                "Fix this by removing the %sannotation of %s "
                "or drop the export.\n",
                tosym, sec2annotation(tosec), sec2annotation(tosec), tosym);
-       case NO_MISMATCH:
-               /* To get warnings on missing members */
                break;
        }
        fprintf(stderr, "\n");
@@ -1286,11 +1309,11 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf,
                                    Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
 {
        const char *tosec;
-       enum mismatch mismatch;
+       const struct sectioncheck *mismatch;
 
        tosec = sec_name(elf, sym->st_shndx);
        mismatch = section_mismatch(fromsec, tosec);
-       if (mismatch != NO_MISMATCH) {
+       if (mismatch) {
                Elf_Sym *to;
                Elf_Sym *from;
                const char *tosym;
@@ -1302,7 +1325,8 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf,
                tosym = sym_name(elf, to);
 
                /* check whitelist - we may ignore it */
-               if (secref_whitelist(fromsec, fromsym, tosec, tosym)) {
+               if (secref_whitelist(mismatch,
+                                       fromsec, fromsym, tosec, tosym)) {
                        report_sec_mismatch(modname, mismatch,
                           fromsec, r->r_offset, fromsym,
                           is_function(from), tosec, tosym,
@@ -1318,7 +1342,7 @@ static unsigned int *reloc_location(struct elf_info *elf,
        int section = sechdr->sh_info;
 
        return (void *)elf->hdr + sechdrs[section].sh_offset +
-               (r->r_offset - sechdrs[section].sh_addr);
+               r->r_offset - sechdrs[section].sh_addr;
 }
 
 static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
index c6e88c652c2f941647f0d04b3cd982fc6c4e7ab5..361d0f71184bbf6748f1251cef81ef07f14c6129 100755 (executable)
@@ -175,12 +175,11 @@ sub do_nm
        }
        if (! -e "$source.c" && ! -e "$source.S") {
                # No obvious source, exclude the object if it is conglomerate
-               if (! open(OBJDUMPDATA, "$objdump $basename|")) {
-                       printf STDERR "$objdump $fullname failed $!\n";
-                       return;
-               }
+               open(my $objdumpdata, "$objdump $basename|")
+                   or die "$objdump $fullname failed $!\n";
+
                my $comment;
-               while (<OBJDUMPDATA>) {
+               while (<$objdumpdata>) {
                        chomp();
                        if (/^In archive/) {
                                # Archives are always conglomerate
@@ -190,18 +189,18 @@ sub do_nm
                        next if (! /^[ 0-9a-f]{5,} /);
                        $comment .= substr($_, 43);
                }
-               close(OBJDUMPDATA);
+               close($objdumpdata);
+
                if (!defined($comment) || $comment !~ /GCC\:.*GCC\:/m) {
                        printf STDERR "No source file found for $fullname\n";
                }
                return;
        }
-       if (! open(NMDATA, "$nm $basename|")) {
-               printf STDERR "$nm $fullname failed $!\n";
-               return;
-       }
+       open (my $nmdata, "$nm $basename|")
+           or die "$nm $fullname failed $!\n";
+
        my @nmdata;
-       while (<NMDATA>) {
+       while (<$nmdata>) {
                chop;
                ($type, $name) = (split(/ +/, $_, 3))[1..2];
                # Expected types
@@ -268,7 +267,8 @@ sub do_nm
                        }
                }
        }
-       close(NMDATA);
+       close($nmdata);
+
        if ($#nmdata < 0) {
                if (
                        $fullname ne "lib/brlock.o"
@@ -316,8 +316,7 @@ sub drop_def
 
 sub list_multiply_defined
 {
-       my ($name, $module);
-       foreach $name (keys(%def)) {
+       foreach my $name (keys(%def)) {
                if ($#{$def{$name}} > 0) {
                        # Special case for cond_syscall
                        if ($#{$def{$name}} == 1 && $name =~ /^sys_/ &&
@@ -333,8 +332,9 @@ sub list_multiply_defined
                                &drop_def("arch/x86/kernel/vsyscall-sysenter_32.o", $name);
                                next;
                        }
+
                        printf "$name is multiply defined in :-\n";
-                       foreach $module (@{$def{$name}}) {
+                       foreach my $module (@{$def{$name}}) {
                                printf "\t$module\n";
                        }
                }
@@ -343,12 +343,13 @@ sub list_multiply_defined
 
 sub resolve_external_references
 {
-       my ($object, $type, $name, $i, $j, $kstrtab, $ksymtab, $export);
+       my ($kstrtab, $ksymtab, $export);
+
        printf "\n";
-       foreach $object (keys(%nmdata)) {
+       foreach my $object (keys(%nmdata)) {
                my $nmdata = $nmdata{$object};
-               for ($i = 0; $i <= $#{$nmdata}; ++$i) {
-                       ($type, $name) = split(' ', $nmdata->[$i], 2);
+               for (my $i = 0; $i <= $#{$nmdata}; ++$i) {
+                       my ($type, $name) = split(' ', $nmdata->[$i], 2);
                        if ($type eq "U" || $type eq "w") {
                                if (exists($def{$name}) || exists($ksymtab{$name})) {
                                        # add the owning object to the nmdata
@@ -357,7 +358,7 @@ sub resolve_external_references
                                        $kstrtab = "R __kstrtab_$name";
                                        $ksymtab = "R __ksymtab_$name";
                                        $export = 0;
-                                       for ($j = 0; $j <= $#{$nmdata}; ++$j) {
+                                       for (my $j = 0; $j <= $#{$nmdata}; ++$j) {
                                                if ($nmdata->[$j] eq $kstrtab ||
                                                    $nmdata->[$j] eq $ksymtab) {
                                                        $export = 1;
@@ -424,11 +425,11 @@ sub resolve_external_references
 sub list_extra_externals
 {
        my %noref = ();
-       my ($name, @module, $module, $export);
-       foreach $name (keys(%def)) {
+
+       foreach my $name (keys(%def)) {
                if (! exists($ref{$name})) {
-                       @module = @{$def{$name}};
-                       foreach $module (@module) {
+                       my @module = @{$def{$name}};
+                       foreach my $module (@module) {
                                if (! exists($noref{$module})) {
                                        $noref{$module} = [];
                                }
@@ -438,16 +439,16 @@ sub list_extra_externals
        }
        if (%noref) {
                printf "\nExternally defined symbols with no external references\n";
-               foreach $module (sort(keys(%noref))) {
+               foreach my $module (sort(keys(%noref))) {
                        printf "  $module\n";
                        foreach (sort(@{$noref{$module}})) {
-                               if (exists($export{$_})) {
-                                       $export = " (export only)";
-                               }
-                               else {
-                                       $export = "";
-                               }
-                               printf "    $_$export\n";
+                           my $export;
+                           if (exists($export{$_})) {
+                               $export = " (export only)";
+                           } else {
+                               $export = "";
+                           }
+                           printf "    $_$export\n";
                        }
                }
        }
index 62fcc3a7f4d35f4ae29c959baac684f154c9aafd..3a681ef25306ba0a98cfaedf7412c24c9af11adb 100644 (file)
@@ -44,7 +44,7 @@ rpm-pkg rpm: $(objtree)/kernel.spec FORCE
        fi
        $(MAKE) clean
        $(PREV) ln -sf $(srctree) $(KERNELPATH)
-       $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion > $(objtree)/.scmversion
+       $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion --scm-only > $(objtree)/.scmversion
        $(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/.
        $(PREV) rm $(KERNELPATH)
        rm -f $(objtree)/.scmversion
index 8b357b0bd250b0e04012a08815c01cd3f95f22a3..07f2fbde2abf85a5f92040a10608a38e23db3905 100644 (file)
@@ -18,6 +18,8 @@ create_package() {
        cp debian/copyright "$pdir/usr/share/doc/$pname/"
        cp debian/changelog "$pdir/usr/share/doc/$pname/changelog.Debian"
        gzip -9 "$pdir/usr/share/doc/$pname/changelog.Debian"
+       sh -c "cd '$pdir'; find . -type f ! -path './DEBIAN/*' -printf '%P\0' \
+               | xargs -r0 md5sum > DEBIAN/md5sums"
 
        # Fix ownership and permissions
        chown -R root:root "$pdir"
index fa27f3dac76992c3e37fa49bbfc61e294464d306..15440f55aef67f05d071156570b7f8e5c14927d6 100755 (executable)
@@ -39,7 +39,7 @@ if ! $PREBUILT; then
 echo "Source: kernel-$__KERNELRELEASE.tar.gz"
 fi
 
-echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root"
+echo "BuildRoot: %{_tmppath}/%{name}-%{PACKAGE_VERSION}-root"
 echo "Provides: $PROVIDES"
 echo "%define __spec_install_post /usr/lib/rpm/brp-compress || :"
 echo "%define debug_package %{nil}"
index cb4260ebdb9192a91a93e2244ca45adc86efcc9b..6943fa7cc95b646d9f1a10752cf2577f4b1a2185 100644 (file)
@@ -7,15 +7,13 @@
 # usage:
 #       readprofile | sort -rn | perl profile2linkerlist.pl > functionlist
 #
+use strict;
 
 while (<>) {
   my $line = $_;
 
   $_ =~ /\W*[0-9]+\W*([a-zA-Z\_0-9]+)\W*[0-9]+/;
 
-  if ( ($line =~ /unknown/) || ($line =~ /total/)) {
-
-  } else {
-    print "*(.text.$1)\n";
-  }
+  print "*(.text.$1)\n"
+      unless ($line =~ /unknown/) || ($line =~ /total/);
 }
index 4c79660793cf31b79f83aec51ac0a9aaaedd5566..44423b4dcb820959b82f6bf126e42a6c6d08f44c 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
 #
 # rt-mutex tester
 #
index 46989b88d7345d233ce5d734e2ed9845784df4d0..d6a866ed1835c8f1ee4524c6bb26df554c83c6e1 100755 (executable)
 #
 
 usage() {
-       echo "Usage: $0 [srctree]" >&2
+       echo "Usage: $0 [--scm-only] [srctree]" >&2
        exit 1
 }
 
-cd "${1:-.}" || usage
+scm_only=false
+srctree=.
+if test "$1" = "--scm-only"; then
+       scm_only=true
+       shift
+fi
+if test $# -gt 0; then
+       srctree=$1
+       shift
+fi
+if test $# -gt 0 -o ! -d "$srctree"; then
+       usage
+fi
 
-# Check for git and a git repo.
-if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
+scm_version()
+{
+       local short=false
 
-       # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore it,
-       # because this version is defined in the top level Makefile.
-       if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
+       cd "$srctree"
+       if test -e .scmversion; then
+               cat "$_"
+               return
+       fi
+       if test "$1" = "--short"; then
+               short=true
+       fi
 
-               # If we are past a tagged commit (like "v2.6.30-rc5-302-g72357d5"),
-               # we pretty print it.
-               if atag="`git describe 2>/dev/null`"; then
-                       echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+       # Check for git and a git repo.
+       if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
+
+               # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
+               # it, because this version is defined in the top level Makefile.
+               if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
+
+                       # If only the short version is requested, don't bother
+                       # running further git commands
+                       if $short; then
+                               echo "+"
+                               return
+                       fi
+                       # If we are past a tagged commit (like
+                       # "v2.6.30-rc5-302-g72357d5"), we pretty print it.
+                       if atag="`git describe 2>/dev/null`"; then
+                               echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+
+                       # If we don't have a tag at all we print -g{commitish}.
+                       else
+                               printf '%s%s' -g $head
+                       fi
+               fi
 
-               # If we don't have a tag at all we print -g{commitish}.
-               else
-                       printf '%s%s' -g $head
+               # Is this git on svn?
+               if git config --get svn-remote.svn.url >/dev/null; then
+                       printf -- '-svn%s' "`git svn find-rev $head`"
                fi
-       fi
 
-       # Is this git on svn?
-       if git config --get svn-remote.svn.url >/dev/null; then
-               printf -- '-svn%s' "`git svn find-rev $head`"
-       fi
+               # Update index only on r/w media
+               [ -w . ] && git update-index --refresh --unmerged > /dev/null
 
-       # Update index only on r/w media
-       [ -w . ] && git update-index --refresh --unmerged > /dev/null
+               # Check for uncommitted changes
+               if git diff-index --name-only HEAD | grep -v "^scripts/package" \
+                   | read dummy; then
+                       printf '%s' -dirty
+               fi
 
-       # Check for uncommitted changes
-       if git diff-index --name-only HEAD | grep -v "^scripts/package" \
-           | read dummy; then
-               printf '%s' -dirty
+               # All done with git
+               return
        fi
 
-       # All done with git
-       exit
-fi
+       # Check for mercurial and a mercurial repo.
+       if hgid=`hg id 2>/dev/null`; then
+               tag=`printf '%s' "$hgid" | cut -d' ' -f2`
+
+               # Do we have an untagged version?
+               if [ -z "$tag" -o "$tag" = tip ]; then
+                       id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
+                       printf '%s%s' -hg "$id"
+               fi
 
-# Check for mercurial and a mercurial repo.
-if hgid=`hg id 2>/dev/null`; then
-       tag=`printf '%s' "$hgid" | cut -d' ' -f2`
+               # Are there uncommitted changes?
+               # These are represented by + after the changeset id.
+               case "$hgid" in
+                       *+|*+\ *) printf '%s' -dirty ;;
+               esac
 
-       # Do we have an untagged version?
-       if [ -z "$tag" -o "$tag" = tip ]; then
-               id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
-               printf '%s%s' -hg "$id"
+               # All done with mercurial
+               return
        fi
 
-       # Are there uncommitted changes?
-       # These are represented by + after the changeset id.
-       case "$hgid" in
-               *+|*+\ *) printf '%s' -dirty ;;
-       esac
+       # Check for svn and a svn repo.
+       if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
+               rev=`echo $rev | awk '{print $NF}'`
+               printf -- '-svn%s' "$rev"
 
-       # All done with mercurial
+               # All done with svn
+               return
+       fi
+}
+
+collect_files()
+{
+       local file res
+
+       for file; do
+               case "$file" in
+               *\~*)
+                       continue
+                       ;;
+               esac
+               if test -e "$file"; then
+                       res="$res$(cat "$file")"
+               fi
+       done
+       echo "$res"
+}
+
+if $scm_only; then
+       scm_version
        exit
 fi
 
-# Check for svn and a svn repo.
-if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
-       rev=`echo $rev | awk '{print $NF}'`
-       printf -- '-svn%s' "$rev"
+if test -e include/config/auto.conf; then
+       source "$_"
+else
+       echo "Error: kernelrelease not valid - run 'make prepare' to update it"
+       exit 1
+fi
 
-       # All done with svn
-       exit
+# localversion* files in the build and source directory
+res="$(collect_files localversion*)"
+if test ! "$srctree" -ef .; then
+       res="$res$(collect_files "$srctree"/localversion*)"
+fi
+
+# CONFIG_LOCALVERSION and LOCALVERSION (if set)
+res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}"
+
+# scm version string if not at a tagged commit
+if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then
+       # full scm version string
+       res="$res$(scm_version)"
+else
+       # apped a plus sign if the repository is not in a clean tagged
+       # state and  LOCALVERSION= is not specified
+       if test "${LOCALVERSION+set}" != "set"; then
+               scm=$(scm_version --short)
+               res="$res${scm:++}"
+       fi
 fi
+
+echo "$res"
index 48a706ab3d0c3d591e4b6758c58852a7a64f8a89..17df3051747a93ee68a75255764408c813f1a14e 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
 #
 # show_deltas: Read list of printk messages instrumented with
 # time data, and format with time deltas.
index 1a0c44d7c4a75308ca6addf915a6951cf30a603d..8509bb51293530fae488f60594199031cd16bf07 100755 (executable)
@@ -5,7 +5,7 @@
 # mode may be any of: tags, TAGS, cscope
 #
 # Uses the following environment variables:
-# ARCH, SUBARCH, srctree, src, obj
+# ARCH, SUBARCH, SRCARCH, srctree, src, obj
 
 if [ "$KBUILD_VERBOSE" = "1" ]; then
        set -x
@@ -17,28 +17,48 @@ ignore="( -name SCCS -o -name BitKeeper -o -name .svn -o \
           -name .git )                                   \
           -prune -o"
 
-# Do not use full path is we do not use O=.. builds
+# Do not use full path if we do not use O=.. builds
+# Use make O=. {tags|cscope}
+# to force full paths for a non-O= build
 if [ "${KBUILD_SRC}" = "" ]; then
        tree=
 else
        tree=${srctree}/
 fi
 
+# Find all available archs
+find_all_archs()
+{
+       ALLSOURCE_ARCHS=""
+       for arch in `ls ${tree}arch`; do
+               ALLSOURCE_ARCHS="${ALLSOURCE_ARCHS} "${arch##\/}
+       done
+}
+
 # Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH
 if [ "${ALLSOURCE_ARCHS}" = "" ]; then
        ALLSOURCE_ARCHS=${SRCARCH}
+elif [ "${ALLSOURCE_ARCHS}" = "all" ]; then
+       find_all_archs
 fi
 
 # find sources in arch/$ARCH
 find_arch_sources()
 {
-       find ${tree}arch/$1 $ignore -name "$2" -print;
+       for i in $archincludedir; do
+               prune="$prune -wholename $i -prune -o"
+       done
+       find ${tree}arch/$1 $ignore $prune -name "$2" -print;
 }
 
 # find sources in arch/$1/include
 find_arch_include_sources()
 {
-       find ${tree}arch/$1/include $ignore -name "$2" -print;
+       include=$(find ${tree}arch/$1/ -name include -type d);
+       if [ -n "$include" ]; then
+               archincludedir="$archincludedir $include"
+               find $include $ignore -name "$2" -print;
+       fi
 }
 
 # find sources in include/
@@ -63,14 +83,15 @@ find_sources()
 
 all_sources()
 {
-       for arch in $ALLSOURCE_ARCHS
-       do
-               find_sources $arch '*.[chS]'
-       done
+       find_arch_include_sources ${SRCARCH} '*.[chS]'
        if [ ! -z "$archinclude" ]; then
                find_arch_include_sources $archinclude '*.[chS]'
        fi
        find_include_sources '*.[chS]'
+       for arch in $ALLSOURCE_ARCHS
+       do
+               find_sources $arch '*.[chS]'
+       done
        find_other_sources '*.[chS]'
 }
 
@@ -89,13 +110,7 @@ all_defconfigs()
 
 docscope()
 {
-       # always use absolute paths for cscope, as recommended by cscope
-       # upstream
-       case "$tree" in
-               /*) ;;
-               *) tree=$PWD/$tree ;;
-       esac
-       (cd /; echo \-k; echo \-q; all_sources) > cscope.files
+       (echo \-k; echo \-q; all_sources) > cscope.files
        cscope -b -f cscope.out
 }
 
index 13074b4547433ab20929fa493114b507c9e4389f..6261745e44591acd65bb47e18e9f65b9e842bfe5 100644 (file)
@@ -33,7 +33,7 @@ static int key_get_type_from_user(char *type,
        ret = strncpy_from_user(type, _type, len);
 
        if (ret < 0)
-               return -EFAULT;
+               return ret;
 
        if (ret == 0 || ret >= len)
                return -EINVAL;
@@ -1080,7 +1080,7 @@ set:
        return old_setting;
 error:
        abort_creds(new);
-       return -EINVAL;
+       return ret;
 
 } /* end keyctl_set_reqkey_keyring() */
 
index 67893372173581601fbcd5c71ca9c30cab0b5a7a..3ff8cc5f487a832c6620b656cb477797695c2f70 100644 (file)
@@ -437,9 +437,11 @@ static int i2sbus_shutdown(struct macio_dev* dev)
 }
 
 static struct macio_driver i2sbus_drv = {
-       .name = "soundbus-i2s",
-       .owner = THIS_MODULE,
-       .match_table = i2sbus_match,
+       .driver = {
+               .name = "soundbus-i2s",
+               .owner = THIS_MODULE,
+               .of_match_table = i2sbus_match,
+       },
        .probe = i2sbus_probe,
        .remove = i2sbus_remove,
 #ifdef CONFIG_PM
index 428121a7e705e88610058b432756c62b32d5277a..10c3a871a12d904bad20cff78dfce56e8373cb92 100644 (file)
@@ -657,7 +657,7 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)
        if (sr & AC97C_SR_CAEVT) {
                struct snd_pcm_runtime *runtime;
                int offset, next_period, block_size;
-               dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n",
+               dev_dbg(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n",
                                casr & AC97C_CSR_OVRUN   ? " OVRUN"   : "",
                                casr & AC97C_CSR_RXRDY   ? " RXRDY"   : "",
                                casr & AC97C_CSR_UNRUN   ? " UNRUN"   : "",
index f74c7372b3d14d3ba553cc8b904dd75585b28bd3..1db586af4f9c8189fda494d2aead7f9c6c22f954 100644 (file)
@@ -2578,6 +2578,9 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
        if (err)
                return -err;
 
+       memset(&prev_ctl, 0, sizeof(prev_ctl));
+       prev_ctl.control_type = -1;
+
        for (idx = 0; idx < 2000; idx++) {
                err = hpi_mixer_get_control_by_index(
                                ss, asihpi->h_mixer,
index e89991ea35439c7ea122777ee3bd284feaa47535..3b44134482266ff5f17ddeb301b258846a34eb77 100644 (file)
@@ -941,11 +941,11 @@ static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
 
 }
 
-static long outstream_get_space_available(struct hpi_hostbuffer_status
+static u32 outstream_get_space_available(struct hpi_hostbuffer_status
        *status)
 {
-       return status->size_in_bytes - ((long)(status->host_index) -
-               (long)(status->dSP_index));
+       return status->size_in_bytes - (status->host_index -
+               status->dSP_index);
 }
 
 static void outstream_write(struct hpi_adapter_obj *pao,
@@ -954,7 +954,7 @@ static void outstream_write(struct hpi_adapter_obj *pao,
        struct hpi_hw_obj *phw = pao->priv;
        struct bus_master_interface *interface = phw->p_interface_buffer;
        struct hpi_hostbuffer_status *status;
-       long space_available;
+       u32 space_available;
 
        if (!phw->outstream_host_buffer_size[phm->obj_index]) {
                /* there  is no BBM buffer, write via message */
@@ -1007,7 +1007,7 @@ static void outstream_write(struct hpi_adapter_obj *pao,
        }
 
        space_available = outstream_get_space_available(status);
-       if (space_available < (long)phm->u.d.u.data.data_size) {
+       if (space_available < phm->u.d.u.data.data_size) {
                phr->error = HPI_ERROR_INVALID_DATASIZE;
                return;
        }
@@ -1018,7 +1018,7 @@ static void outstream_write(struct hpi_adapter_obj *pao,
                && hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
                                obj_index])) {
                u8 *p_bbm_data;
-               long l_first_write;
+               u32 l_first_write;
                u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
 
                if (hpios_locked_mem_get_virt_addr(&phw->
@@ -1248,9 +1248,9 @@ static void instream_start(struct hpi_adapter_obj *pao,
        hw_message(pao, phm, phr);
 }
 
-static long instream_get_bytes_available(struct hpi_hostbuffer_status *status)
+static u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status)
 {
-       return (long)(status->dSP_index) - (long)(status->host_index);
+       return status->dSP_index - status->host_index;
 }
 
 static void instream_read(struct hpi_adapter_obj *pao,
@@ -1259,9 +1259,9 @@ static void instream_read(struct hpi_adapter_obj *pao,
        struct hpi_hw_obj *phw = pao->priv;
        struct bus_master_interface *interface = phw->p_interface_buffer;
        struct hpi_hostbuffer_status *status;
-       long data_available;
+       u32 data_available;
        u8 *p_bbm_data;
-       long l_first_read;
+       u32 l_first_read;
        u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
 
        if (!phw->instream_host_buffer_size[phm->obj_index]) {
@@ -1272,7 +1272,7 @@ static void instream_read(struct hpi_adapter_obj *pao,
 
        status = &interface->instream_host_buffer_status[phm->obj_index];
        data_available = instream_get_bytes_available(status);
-       if (data_available < (long)phm->u.d.u.data.data_size) {
+       if (data_available < phm->u.d.u.data.data_size) {
                phr->error = HPI_ERROR_INVALID_DATASIZE;
                return;
        }
index dc79564fea30d2e17fef0b9abfc51b0ec636c73f..1df25cf5ce38c35f0d04fdddd43be9ea1d23c3f4 100644 (file)
@@ -1913,11 +1913,11 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
        if (WARN_ONCE(!azx_dev->period_bytes,
                      "hda-intel: zero azx_dev->period_bytes"))
                return -1; /* this shouldn't happen! */
-       if (wallclk <= azx_dev->period_wallclk &&
+       if (wallclk < (azx_dev->period_wallclk * 5) / 4 &&
            pos % azx_dev->period_bytes > azx_dev->period_bytes / 2)
                /* NG - it's below the first next period boundary */
                return bdl_pos_adj[chip->dev_index] ? 0 : -1;
-       azx_dev->start_wallclk = wallclk;
+       azx_dev->start_wallclk += wallclk;
        return 1; /* OK, it's fine */
 }
 
@@ -2288,6 +2288,8 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB),
@@ -2296,6 +2298,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1849, 0x0888, "775Dual-VSTA", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x8086, 0xd601, "eMachines T5212", POS_FIX_LPIB),
        {}
index 17d4548cc353f72402693b0b39461226467a00d9..f1ce7d7f5aa3b4649e083b92e80b9fd57508c839 100644 (file)
@@ -2619,16 +2619,18 @@ static int alc_build_controls(struct hda_codec *codec)
        }
 
        /* assign Capture Source enums to NID */
-       kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
-       if (!kctl)
-               kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
-       for (i = 0; kctl && i < kctl->count; i++) {
-               hda_nid_t *nids = spec->capsrc_nids;
-               if (!nids)
-                       nids = spec->adc_nids;
-               err = snd_hda_add_nid(codec, kctl, i, nids[i]);
-               if (err < 0)
-                       return err;
+       if (spec->capsrc_nids || spec->adc_nids) {
+               kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
+               if (!kctl)
+                       kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
+               for (i = 0; kctl && i < kctl->count; i++) {
+                       hda_nid_t *nids = spec->capsrc_nids;
+                       if (!nids)
+                               nids = spec->adc_nids;
+                       err = snd_hda_add_nid(codec, kctl, i, nids[i]);
+                       if (err < 0)
+                               return err;
+               }
        }
        if (spec->cap_mixer) {
                const char *kname = kctl ? kctl->id.name : NULL;
@@ -6948,7 +6950,7 @@ static struct hda_input_mux mb5_capture_source = {
        .num_items = 3,
        .items = {
                { "Mic", 0x1 },
-               { "Line", 0x2 },
+               { "Line", 0x7 },
                { "CD", 0x4 },
        },
 };
@@ -7469,8 +7471,8 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = {
        HDA_BIND_MUTE   ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
        HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
-       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-       HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
+       HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
@@ -7853,10 +7855,9 @@ static struct hda_verb alc885_mb5_init_verbs[] = {
        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
        { }
 };
 
@@ -9476,6 +9477,10 @@ static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
        SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
        SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
+       SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31),
+       SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_ASUS_A7M),
+       SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3),
+       SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21),
        SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
        SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
        SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
index 79f0f4ad242c1be8bfb00694ff1e011016942f90..d3955096d87214e842d3ba25d0e45aedf3fbcc12 100644 (file)
@@ -612,7 +612,6 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
                                                                NUMDMA_MASK);
                mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
                                ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
        }
 
        if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -623,7 +622,6 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
                                                                NUMDMA_MASK);
                mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
                                ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
        }
 }
 
index 22208b373fb90fd64bd294d4f8eeb6a90ab841b1..e1ec6d91ea3829dfc1d44d4d5995d2a562d54fce 100644 (file)
@@ -73,7 +73,7 @@ struct psc_dma {
 };
 
 /* Utility for retrieving psc_dma_stream structure from a substream */
-inline struct psc_dma_stream *
+static inline struct psc_dma_stream *
 to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma)
 {
        if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
index eba9b9d257a109b3e4554581cc97f9d6fe839035..252defea93b5f2fdc4e64ad9ae4c484e2b8d9eca 100644 (file)
@@ -13,9 +13,18 @@ config SND_MXC_SOC_SSI
 
 config SND_MXC_SOC_WM1133_EV1
        tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"
-       depends on SND_IMX_SOC && EXPERIMENTAL
+       depends on SND_IMX_SOC && MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
        select SND_SOC_WM8350
        select SND_MXC_SOC_SSI
        help
          Enable support for audio on the i.MX31ADS with the WM1133-EV1
          PMIC board with WM8835x fitted.
+
+config SND_SOC_PHYCORE_AC97
+       tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
+       depends on MACH_PCM043 || MACH_PCA100
+       select SND_MXC_SOC_SSI
+       select SND_SOC_WM9712
+       help
+         Say Y if you want to add support for SoC audio on Phytec phyCORE
+         and phyCARD boards in AC97 mode
index 1941a357e8c4f69fddf94a9a682d2fa0ebaf7d61..d256f5f313b5a0e10ac5158dc422741f08ec6cd3 100644 (file)
@@ -328,38 +328,6 @@ static struct snd_soc_device spitz_snd_devdata = {
        .codec_dev = &soc_codec_dev_wm8750,
 };
 
-/*
- * FIXME: This is a temporary bodge to avoid cross-tree merge issues.
- * New drivers should register the wm8750 I2C device in the machine
- * setup code (under arch/arm for ARM systems).
- */
-static int wm8750_i2c_register(void)
-{
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = 0x1b;
-       strlcpy(info.type, "wm8750", I2C_NAME_SIZE);
-
-       adapter = i2c_get_adapter(0);
-       if (!adapter) {
-               printk(KERN_ERR "can't get i2c adapter 0\n");
-               return -ENODEV;
-       }
-
-       client = i2c_new_device(adapter, &info);
-       i2c_put_adapter(adapter);
-       if (!client) {
-               printk(KERN_ERR "can't add i2c device at 0x%x\n",
-               (unsigned int)info.addr);
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
 static struct platform_device *spitz_snd_device;
 
 static int __init spitz_init(void)
@@ -369,10 +337,6 @@ static int __init spitz_init(void)
        if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita()))
                return -ENODEV;
 
-       ret = wm8750_i2c_setup();
-       if (ret != 0)
-               return ret;
-
        spitz_snd_device = platform_device_alloc("soc-audio", -1);
        if (!spitz_snd_device)
                return -ENOMEM;
index 4c7b051f9d17705bfc9827113e4fc8f74792e7c7..1bc56b2b94e29f9143baa9911f72fa962202d17a 100644 (file)
@@ -69,7 +69,6 @@ struct snd_at73c213 {
        int                             irq;
        int                             period;
        unsigned long                   bitrate;
-       struct clk                      *bitclk;
        struct ssc_device               *ssc;
        struct spi_device               *spi;
        u8                              spi_wbuffer[2];
index e7ac7f493a8fa1d0874ca9992ee180679390ec69..1e362bf8834f4e5fdfc6da32cf33a96f53ef7c85 100644 (file)
@@ -11,7 +11,8 @@ snd-usb-audio-objs :=         card.o \
                        endpoint.o \
                        urb.o \
                        pcm.o \
-                       helper.o
+                       helper.o \
+                       clock.o
 
 snd-usbmidi-lib-objs := midi.o
 
index da1346bd4856893a5e2449abfe0d6cd1e6293ea5..7a8ac1d81be7fc7e1a176ad432cd43a841a9e74d 100644 (file)
@@ -236,7 +236,6 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
        }
 
        case UAC_VERSION_2: {
-               struct uac_clock_source_descriptor *cs;
                struct usb_interface_assoc_descriptor *assoc =
                        usb_ifnum_to_if(dev, ctrlif)->intf_assoc;
 
@@ -245,21 +244,6 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
                        return -EINVAL;
                }
 
-               /* FIXME: for now, we expect there is at least one clock source
-                * descriptor and we always take the first one.
-                * We should properly support devices with multiple clock sources,
-                * clock selectors and sample rate conversion units. */
-
-               cs = snd_usb_find_csint_desc(host_iface->extra, host_iface->extralen,
-                                               NULL, UAC2_CLOCK_SOURCE);
-
-               if (!cs) {
-                       snd_printk(KERN_ERR "CLOCK_SOURCE descriptor not found\n");
-                       return -EINVAL;
-               }
-
-               chip->clock_id = cs->bClockID;
-
                for (i = 0; i < assoc->bInterfaceCount; i++) {
                        int intf = assoc->bFirstInterface + i;
 
@@ -481,6 +465,8 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
                        goto __error;
        }
 
+       chip->ctrl_intf = alts;
+
        if (err > 0) {
                /* create normal USB audio interfaces */
                if (snd_usb_create_streams(chip, ifnum) < 0 ||
index ed92420c10957150f30db2891191ffe60bf4b0c3..1febf2f23754afc63eb5469450ac8da6a97f23b3 100644 (file)
@@ -25,6 +25,7 @@ struct audioformat {
        unsigned int rate_min, rate_max;        /* min/max rates */
        unsigned int nr_rates;          /* number of rate table entries */
        unsigned int *rate_table;       /* rate table */
+       unsigned char clock;            /* associated clock */
 };
 
 struct snd_usb_substream;
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
new file mode 100644 (file)
index 0000000..b585511
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ *   Clock domain and sample rate management functions
+ *
+ *   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/bitops.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/usb.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/audio-v2.h>
+
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+
+#include "usbaudio.h"
+#include "card.h"
+#include "midi.h"
+#include "mixer.h"
+#include "proc.h"
+#include "quirks.h"
+#include "endpoint.h"
+#include "helper.h"
+#include "debug.h"
+#include "pcm.h"
+#include "urb.h"
+#include "format.h"
+
+static struct uac_clock_source_descriptor *
+       snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface,
+                                 int clock_id)
+{
+       struct uac_clock_source_descriptor *cs = NULL;
+
+       while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
+                                            ctrl_iface->extralen,
+                                            cs, UAC2_CLOCK_SOURCE))) {
+               if (cs->bClockID == clock_id)
+                       return cs;
+       }
+
+       return NULL;
+}
+
+static struct uac_clock_selector_descriptor *
+       snd_usb_find_clock_selector(struct usb_host_interface *ctrl_iface,
+                                   int clock_id)
+{
+       struct uac_clock_selector_descriptor *cs = NULL;
+
+       while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
+                                            ctrl_iface->extralen,
+                                            cs, UAC2_CLOCK_SELECTOR))) {
+               if (cs->bClockID == clock_id)
+                       return cs;
+       }
+
+       return NULL;
+}
+
+static struct uac_clock_multiplier_descriptor *
+       snd_usb_find_clock_multiplier(struct usb_host_interface *ctrl_iface,
+                                     int clock_id)
+{
+       struct uac_clock_multiplier_descriptor *cs = NULL;
+
+       while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
+                                            ctrl_iface->extralen,
+                                            cs, UAC2_CLOCK_MULTIPLIER))) {
+               if (cs->bClockID == clock_id)
+                       return cs;
+       }
+
+       return NULL;
+}
+
+static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
+{
+       unsigned char buf;
+       int ret;
+
+       ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
+                             UAC2_CS_CUR,
+                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+                             UAC2_CX_CLOCK_SELECTOR << 8,
+                             snd_usb_ctrl_intf(chip) | (selector_id << 8),
+                             &buf, sizeof(buf), 1000);
+
+       if (ret < 0)
+               return ret;
+
+       return buf;
+}
+
+static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
+{
+       int err;
+       unsigned char data;
+       struct usb_device *dev = chip->dev;
+
+       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
+                             snd_usb_ctrl_intf(chip) | (source_id << 8),
+                             &data, sizeof(data), 1000);
+
+       if (err < 0) {
+               snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n",
+                          __func__, source_id);
+               return err;
+       }
+
+       return !!data;
+}
+
+/* Try to find the clock source ID of a given clock entity */
+
+static int __uac_clock_find_source(struct snd_usb_audio *chip,
+                                  struct usb_host_interface *host_iface,
+                                  int entity_id, unsigned long *visited)
+{
+       struct uac_clock_source_descriptor *source;
+       struct uac_clock_selector_descriptor *selector;
+       struct uac_clock_multiplier_descriptor *multiplier;
+
+       entity_id &= 0xff;
+
+       if (test_and_set_bit(entity_id, visited)) {
+               snd_printk(KERN_WARNING
+                       "%s(): recursive clock topology detected, id %d.\n",
+                       __func__, entity_id);
+               return -EINVAL;
+       }
+
+       /* first, see if the ID we're looking for is a clock source already */
+       source = snd_usb_find_clock_source(host_iface, entity_id);
+       if (source)
+               return source->bClockID;
+
+       selector = snd_usb_find_clock_selector(host_iface, entity_id);
+       if (selector) {
+               int ret;
+
+               /* the entity ID we are looking for is a selector.
+                * find out what it currently selects */
+               ret = uac_clock_selector_get_val(chip, selector->bClockID);
+               if (ret < 0)
+                       return ret;
+
+               if (ret > selector->bNrInPins || ret < 1) {
+                       printk(KERN_ERR
+                               "%s(): selector reported illegal value, id %d, ret %d\n",
+                               __func__, selector->bClockID, ret);
+
+                       return -EINVAL;
+               }
+
+               return __uac_clock_find_source(chip, host_iface,
+                                              selector->baCSourceID[ret-1],
+                                              visited);
+       }
+
+       /* FIXME: multipliers only act as pass-thru element for now */
+       multiplier = snd_usb_find_clock_multiplier(host_iface, entity_id);
+       if (multiplier)
+               return __uac_clock_find_source(chip, host_iface,
+                                              multiplier->bCSourceID, visited);
+
+       return -EINVAL;
+}
+
+int snd_usb_clock_find_source(struct snd_usb_audio *chip,
+                             struct usb_host_interface *host_iface,
+                             int entity_id)
+{
+       DECLARE_BITMAP(visited, 256);
+       memset(visited, 0, sizeof(visited));
+       return __uac_clock_find_source(chip, host_iface, entity_id, visited);
+}
+
+static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
+                             struct usb_host_interface *alts,
+                             struct audioformat *fmt, int rate)
+{
+       struct usb_device *dev = chip->dev;
+       unsigned int ep;
+       unsigned char data[3];
+       int err, crate;
+
+       ep = get_endpoint(alts, 0)->bEndpointAddress;
+
+       /* if endpoint doesn't have sampling rate control, bail out */
+       if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) {
+               snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n",
+                                  dev->devnum, iface, fmt->altsetting);
+               return 0;
+       }
+
+       data[0] = rate;
+       data[1] = rate >> 8;
+       data[2] = rate >> 16;
+       if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
+                                  USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+                                  UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
+                                  data, sizeof(data), 1000)) < 0) {
+               snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
+                          dev->devnum, iface, fmt->altsetting, rate, ep);
+               return err;
+       }
+
+       if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
+                                  USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
+                                  UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
+                                  data, sizeof(data), 1000)) < 0) {
+               snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
+                          dev->devnum, iface, fmt->altsetting, ep);
+               return 0; /* some devices don't support reading */
+       }
+
+       crate = data[0] | (data[1] << 8) | (data[2] << 16);
+       if (crate != rate) {
+               snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
+               // runtime->rate = crate;
+       }
+
+       return 0;
+}
+
+static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
+                             struct usb_host_interface *alts,
+                             struct audioformat *fmt, int rate)
+{
+       struct usb_device *dev = chip->dev;
+       unsigned char data[4];
+       int err, crate;
+       int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf, fmt->clock);
+
+       if (clock < 0)
+               return clock;
+
+       if (!uac_clock_source_is_valid(chip, clock)) {
+               snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n",
+                          dev->devnum, iface, fmt->altsetting, clock);
+               return -ENXIO;
+       }
+
+       data[0] = rate;
+       data[1] = rate >> 8;
+       data[2] = rate >> 16;
+       data[3] = rate >> 24;
+       if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
+                                  USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+                                  UAC2_CS_CONTROL_SAM_FREQ << 8,
+                                  snd_usb_ctrl_intf(chip) | (clock << 8),
+                                  data, sizeof(data), 1000)) < 0) {
+               snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
+                          dev->devnum, iface, fmt->altsetting, rate);
+               return err;
+       }
+
+       if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+                                  USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                                  UAC2_CS_CONTROL_SAM_FREQ << 8,
+                                  snd_usb_ctrl_intf(chip) | (clock << 8),
+                                  data, sizeof(data), 1000)) < 0) {
+               snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
+                          dev->devnum, iface, fmt->altsetting);
+               return err;
+       }
+
+       crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+       if (crate != rate)
+               snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
+
+       return 0;
+}
+
+int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
+                            struct usb_host_interface *alts,
+                            struct audioformat *fmt, int rate)
+{
+       struct usb_interface_descriptor *altsd = get_iface_desc(alts);
+
+       switch (altsd->bInterfaceProtocol) {
+       case UAC_VERSION_1:
+               return set_sample_rate_v1(chip, iface, alts, fmt, rate);
+
+       case UAC_VERSION_2:
+               return set_sample_rate_v2(chip, iface, alts, fmt, rate);
+       }
+
+       return -EINVAL;
+}
+
diff --git a/sound/usb/clock.h b/sound/usb/clock.h
new file mode 100644 (file)
index 0000000..beb2536
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __USBAUDIO_CLOCK_H
+#define __USBAUDIO_CLOCK_H
+
+int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
+                            struct usb_host_interface *alts,
+                            struct audioformat *fmt, int rate);
+
+int snd_usb_clock_find_source(struct snd_usb_audio *chip,
+                             struct usb_host_interface *host_iface,
+                             int entity_id);
+
+#endif /* __USBAUDIO_CLOCK_H */
index 28ee1ce3971a7fd063fdfc0f80a8f73696bb9b4b..6f6596cf2b190d0e1f18860a4384bacddbec472f 100644 (file)
@@ -190,6 +190,38 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
        return attributes;
 }
 
+static struct uac2_input_terminal_descriptor *
+       snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+                                              int terminal_id)
+{
+       struct uac2_input_terminal_descriptor *term = NULL;
+
+       while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
+                                              ctrl_iface->extralen,
+                                              term, UAC_INPUT_TERMINAL))) {
+               if (term->bTerminalID == terminal_id)
+                       return term;
+       }
+
+       return NULL;
+}
+
+static struct uac2_output_terminal_descriptor *
+       snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+                                               int terminal_id)
+{
+       struct uac2_output_terminal_descriptor *term = NULL;
+
+       while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
+                                              ctrl_iface->extralen,
+                                              term, UAC_OUTPUT_TERMINAL))) {
+               if (term->bTerminalID == terminal_id)
+                       return term;
+       }
+
+       return NULL;
+}
+
 int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
 {
        struct usb_device *dev;
@@ -199,7 +231,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
        int i, altno, err, stream;
        int format = 0, num_channels = 0;
        struct audioformat *fp = NULL;
-       int num, protocol;
+       int num, protocol, clock = 0;
        struct uac_format_type_i_continuous_descriptor *fmt;
 
        dev = chip->dev;
@@ -263,6 +295,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                }
 
                case UAC_VERSION_2: {
+                       struct uac2_input_terminal_descriptor *input_term;
+                       struct uac2_output_terminal_descriptor *output_term;
                        struct uac_as_header_descriptor_v2 *as =
                                snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
 
@@ -281,7 +315,25 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                        num_channels = as->bNrChannels;
                        format = le32_to_cpu(as->bmFormats);
 
-                       break;
+                       /* lookup the terminal associated to this interface
+                        * to extract the clock */
+                       input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
+                                                                           as->bTerminalLink);
+                       if (input_term) {
+                               clock = input_term->bCSourceID;
+                               break;
+                       }
+
+                       output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
+                                                                             as->bTerminalLink);
+                       if (output_term) {
+                               clock = output_term->bCSourceID;
+                               break;
+                       }
+
+                       snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
+                                  dev->devnum, iface_no, altno, as->bTerminalLink);
+                       continue;
                }
 
                default:
@@ -338,6 +390,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                        fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
                                        * (fp->maxpacksize & 0x7ff);
                fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
+               fp->clock = clock;
 
                /* some quirks for attributes here */
 
@@ -374,6 +427,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
                        kfree(fp->rate_table);
                        kfree(fp);
+                       fp = NULL;
                        continue;
                }
 
index fe29d61de19bc80bdc0dbdc2fe209fd3fd71b21e..30364aba79ccb0e8bef307ccbe166d28799d7464 100644 (file)
@@ -29,6 +29,7 @@
 #include "quirks.h"
 #include "helper.h"
 #include "debug.h"
+#include "clock.h"
 
 /*
  * parse the audio format type I descriptor
@@ -204,6 +205,60 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
        return 0;
 }
 
+/*
+ * Helper function to walk the array of sample rate triplets reported by
+ * the device. The problem is that we need to parse whole array first to
+ * get to know how many sample rates we have to expect.
+ * Then fp->rate_table can be allocated and filled.
+ */
+static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
+                                       const unsigned char *data)
+{
+       int i, nr_rates = 0;
+
+       fp->rates = fp->rate_min = fp->rate_max = 0;
+
+       for (i = 0; i < nr_triplets; i++) {
+               int min = combine_quad(&data[2 + 12 * i]);
+               int max = combine_quad(&data[6 + 12 * i]);
+               int res = combine_quad(&data[10 + 12 * i]);
+               int rate;
+
+               if ((max < 0) || (min < 0) || (res < 0) || (max < min))
+                       continue;
+
+               /*
+                * for ranges with res == 1, we announce a continuous sample
+                * rate range, and this function should return 0 for no further
+                * parsing.
+                */
+               if (res == 1) {
+                       fp->rate_min = min;
+                       fp->rate_max = max;
+                       fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
+                       return 0;
+               }
+
+               for (rate = min; rate <= max; rate += res) {
+                       if (fp->rate_table)
+                               fp->rate_table[nr_rates] = rate;
+                       if (!fp->rate_min || rate < fp->rate_min)
+                               fp->rate_min = rate;
+                       if (!fp->rate_max || rate > fp->rate_max)
+                               fp->rate_max = rate;
+                       fp->rates |= snd_pcm_rate_to_rate_bit(rate);
+
+                       nr_rates++;
+
+                       /* avoid endless loop */
+                       if (res == 0)
+                               break;
+               }
+       }
+
+       return nr_rates;
+}
+
 /*
  * parse the format descriptor and stores the possible sample rates
  * on the audioformat table (audio class v2).
@@ -214,21 +269,30 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
 {
        struct usb_device *dev = chip->dev;
        unsigned char tmp[2], *data;
-       int i, nr_rates, data_size, ret = 0;
+       int nr_triplets, data_size, ret = 0;
+       int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf, fp->clock);
+
+       if (clock < 0) {
+               snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n",
+                               __func__, clock);
+               goto err;
+       }
 
        /* get the number of sample rates first by only fetching 2 bytes */
        ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
                              USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+                             snd_usb_ctrl_intf(chip) | (clock << 8),
                              tmp, sizeof(tmp), 1000);
 
        if (ret < 0) {
-               snd_printk(KERN_ERR "unable to retrieve number of sample rates\n");
+               snd_printk(KERN_ERR "%s(): unable to retrieve number of sample rates (clock %d)\n",
+                               __func__, clock);
                goto err;
        }
 
-       nr_rates = (tmp[1] << 8) | tmp[0];
-       data_size = 2 + 12 * nr_rates;
+       nr_triplets = (tmp[1] << 8) | tmp[0];
+       data_size = 2 + 12 * nr_triplets;
        data = kzalloc(data_size, GFP_KERNEL);
        if (!data) {
                ret = -ENOMEM;
@@ -237,36 +301,40 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
 
        /* now get the full information */
        ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
-                              USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                              UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8,
-                              data, data_size, 1000);
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+                             snd_usb_ctrl_intf(chip) | (clock << 8),
+                             data, data_size, 1000);
 
        if (ret < 0) {
-               snd_printk(KERN_ERR "unable to retrieve sample rate range\n");
+               snd_printk(KERN_ERR "%s(): unable to retrieve sample rate range (clock %d)\n",
+                               __func__, clock);
                ret = -EINVAL;
                goto err_free;
        }
 
-       fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
+       /* Call the triplet parser, and make sure fp->rate_table is NULL.
+        * We just use the return value to know how many sample rates we
+        * will have to deal with. */
+       kfree(fp->rate_table);
+       fp->rate_table = NULL;
+       fp->nr_rates = parse_uac2_sample_rate_range(fp, nr_triplets, data);
+
+       if (fp->nr_rates == 0) {
+               /* SNDRV_PCM_RATE_CONTINUOUS */
+               ret = 0;
+               goto err_free;
+       }
+
+       fp->rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL);
        if (!fp->rate_table) {
                ret = -ENOMEM;
                goto err_free;
        }
 
-       fp->nr_rates = 0;
-       fp->rate_min = fp->rate_max = 0;
-
-       for (i = 0; i < nr_rates; i++) {
-               int rate = combine_quad(&data[2 + 12 * i]);
-
-               fp->rate_table[fp->nr_rates] = rate;
-               if (!fp->rate_min || rate < fp->rate_min)
-                       fp->rate_min = rate;
-               if (!fp->rate_max || rate > fp->rate_max)
-                       fp->rate_max = rate;
-               fp->rates |= snd_pcm_rate_to_rate_bit(rate);
-               fp->nr_rates++;
-       }
+       /* Call the triplet parser again, but this time, fp->rate_table is
+        * allocated, so the rates will be stored */
+       parse_uac2_sample_rate_range(fp, nr_triplets, data);
 
 err_free:
        kfree(data);
index a6b0e51b3a9a2ebae41cb03d3ca80e06e4a07b09..09bd943c43bf736c72c915ce99f41180b6be88b9 100644 (file)
@@ -28,5 +28,9 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
 #define snd_usb_get_speed(dev) ((dev)->speed)
 #endif
 
+static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)
+{
+       return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber;
+}
 
 #endif /* __USBAUDIO_HELPER_H */
index 03ce971e002760e84b2d36565ee0cbfa56bebd50..6939d0f517d9bd42928f87e7f6a4e9fd35bff9b4 100644 (file)
@@ -78,39 +78,6 @@ enum {
        USB_MIXER_U16,
 };
 
-enum {
-       USB_PROC_UPDOWN = 1,
-       USB_PROC_UPDOWN_SWITCH = 1,
-       USB_PROC_UPDOWN_MODE_SEL = 2,
-
-       USB_PROC_PROLOGIC = 2,
-       USB_PROC_PROLOGIC_SWITCH = 1,
-       USB_PROC_PROLOGIC_MODE_SEL = 2,
-
-       USB_PROC_3DENH = 3,
-       USB_PROC_3DENH_SWITCH = 1,
-       USB_PROC_3DENH_SPACE = 2,
-
-       USB_PROC_REVERB = 4,
-       USB_PROC_REVERB_SWITCH = 1,
-       USB_PROC_REVERB_LEVEL = 2,
-       USB_PROC_REVERB_TIME = 3,
-       USB_PROC_REVERB_DELAY = 4,
-
-       USB_PROC_CHORUS = 5,
-       USB_PROC_CHORUS_SWITCH = 1,
-       USB_PROC_CHORUS_LEVEL = 2,
-       USB_PROC_CHORUS_RATE = 3,
-       USB_PROC_CHORUS_DEPTH = 4,
-
-       USB_PROC_DCR = 6,
-       USB_PROC_DCR_SWITCH = 1,
-       USB_PROC_DCR_RATIO = 2,
-       USB_PROC_DCR_MAX_AMP = 3,
-       USB_PROC_DCR_THRESHOLD = 4,
-       USB_PROC_DCR_ATTACK = 5,
-       USB_PROC_DCR_RELEASE = 6,
-};
 
 /*E-mu 0202(0404) eXtension Unit(XU) control*/
 enum {
@@ -198,22 +165,24 @@ static int check_mapped_selector_name(struct mixer_build *state, int unitid,
 
 /*
  * find an audio control unit with the given unit id
- * this doesn't return any clock related units, so they need to be handled elsewhere
  */
 static void *find_audio_control_unit(struct mixer_build *state, unsigned char unit)
 {
-       unsigned char *p;
+       /* we just parse the header */
+       struct uac_feature_unit_descriptor *hdr = NULL;
 
-       p = NULL;
-       while ((p = snd_usb_find_desc(state->buffer, state->buflen, p,
-                                     USB_DT_CS_INTERFACE)) != NULL) {
-               if (p[0] >= 4 && p[2] >= UAC_INPUT_TERMINAL && p[2] <= UAC2_EXTENSION_UNIT_V2 && p[3] == unit)
-                       return p;
+       while ((hdr = snd_usb_find_desc(state->buffer, state->buflen, hdr,
+                                       USB_DT_CS_INTERFACE)) != NULL) {
+               if (hdr->bLength >= 4 &&
+                   hdr->bDescriptorSubtype >= UAC_INPUT_TERMINAL &&
+                   hdr->bDescriptorSubtype <= UAC2_SAMPLE_RATE_CONVERTER &&
+                   hdr->bUnitID == unit)
+                       return hdr;
        }
+
        return NULL;
 }
 
-
 /*
  * copy a string with the given id
  */
@@ -328,27 +297,36 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
 
 static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
 {
-       unsigned char buf[14]; /* enough space for one range of 4 bytes */
+       unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
        unsigned char *val;
-       int ret;
+       int ret, size;
        __u8 bRequest;
 
-       bRequest = (request == UAC_GET_CUR) ?
-               UAC2_CS_CUR : UAC2_CS_RANGE;
+       if (request == UAC_GET_CUR) {
+               bRequest = UAC2_CS_CUR;
+               size = sizeof(__u16);
+       } else {
+               bRequest = UAC2_CS_RANGE;
+               size = sizeof(buf);
+       }
+
+       memset(buf, 0, sizeof(buf));
 
        ret = snd_usb_ctl_msg(cval->mixer->chip->dev,
                              usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
                              bRequest,
                              USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
                              validx, cval->mixer->ctrlif | (cval->id << 8),
-                             buf, sizeof(buf), 1000);
+                             buf, size, 1000);
 
        if (ret < 0) {
-               snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
-                           request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
+               snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
+                          request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
                return ret;
        }
 
+       /* FIXME: how should we handle multiple triplets here? */
+
        switch (request) {
        case UAC_GET_CUR:
                val = buf;
@@ -462,6 +440,16 @@ static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
                             int index, int value)
 {
        int err;
+       unsigned int read_only = (channel == 0) ?
+               cval->master_readonly :
+               cval->ch_readonly & (1 << (channel - 1));
+
+       if (read_only) {
+               snd_printdd(KERN_INFO "%s(): channel %d of control %d is read_only\n",
+                           __func__, channel, cval->control);
+               return 0;
+       }
+
        err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel,
                            value);
        if (err < 0)
@@ -631,6 +619,7 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
  */
 static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term)
 {
+       int err;
        void *p1;
 
        memset(term, 0, sizeof(*term));
@@ -651,6 +640,11 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
                                term->channels = d->bNrChannels;
                                term->chconfig = le32_to_cpu(d->bmChannelConfig);
                                term->name = d->iTerminal;
+
+                               /* call recursively to get the clock selectors */
+                               err = check_input_term(state, d->bCSourceID, term);
+                               if (err < 0)
+                                       return err;
                        }
                        return 0;
                case UAC_FEATURE_UNIT: {
@@ -667,7 +661,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
                        term->name = uac_mixer_unit_iMixer(d);
                        return 0;
                }
-               case UAC_SELECTOR_UNIT: {
+               case UAC_SELECTOR_UNIT:
+               case UAC2_CLOCK_SELECTOR: {
                        struct uac_selector_unit_descriptor *d = p1;
                        /* call recursively to retrieve the channel info */
                        if (check_input_term(state, d->baSourceID[0], term) < 0)
@@ -690,6 +685,13 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
                        term->name = uac_processing_unit_iProcessing(d, state->mixer->protocol);
                        return 0;
                }
+               case UAC2_CLOCK_SOURCE: {
+                       struct uac_clock_source_descriptor *d = p1;
+                       term->type = d->bDescriptorSubtype << 16; /* virtual type */
+                       term->id = id;
+                       term->name = d->iClockSource;
+                       return 0;
+               }
                default:
                        return -ENODEV;
                }
@@ -709,16 +711,20 @@ struct usb_feature_control_info {
 };
 
 static struct usb_feature_control_info audio_feature_info[] = {
-       { "Mute",               USB_MIXER_INV_BOOLEAN },
-       { "Volume",             USB_MIXER_S16 },
+       { "Mute",                       USB_MIXER_INV_BOOLEAN },
+       { "Volume",                     USB_MIXER_S16 },
        { "Tone Control - Bass",        USB_MIXER_S8 },
        { "Tone Control - Mid",         USB_MIXER_S8 },
        { "Tone Control - Treble",      USB_MIXER_S8 },
        { "Graphic Equalizer",          USB_MIXER_S8 }, /* FIXME: not implemeted yet */
-       { "Auto Gain Control",  USB_MIXER_BOOLEAN },
-       { "Delay Control",      USB_MIXER_U16 },
-       { "Bass Boost",         USB_MIXER_BOOLEAN },
-       { "Loudness",           USB_MIXER_BOOLEAN },
+       { "Auto Gain Control",          USB_MIXER_BOOLEAN },
+       { "Delay Control",              USB_MIXER_U16 },
+       { "Bass Boost",                 USB_MIXER_BOOLEAN },
+       { "Loudness",                   USB_MIXER_BOOLEAN },
+       /* UAC2 specific */
+       { "Input Gain Control",         USB_MIXER_U16 },
+       { "Input Gain Pad Control",     USB_MIXER_BOOLEAN },
+       { "Phase Inverter Control",     USB_MIXER_BOOLEAN },
 };
 
 
@@ -958,7 +964,7 @@ static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str)
 static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                              unsigned int ctl_mask, int control,
                              struct usb_audio_term *iterm, int unitid,
-                             int read_only)
+                             int readonly_mask)
 {
        struct uac_feature_unit_descriptor *desc = raw_desc;
        unsigned int len = 0;
@@ -970,7 +976,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
 
        control++; /* change from zero-based to 1-based value */
 
-       if (control == UAC_GRAPHIC_EQUALIZER_CONTROL) {
+       if (control == UAC_FU_GRAPHIC_EQUALIZER) {
                /* FIXME: not supported yet */
                return;
        }
@@ -989,20 +995,25 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
        cval->control = control;
        cval->cmask = ctl_mask;
        cval->val_type = audio_feature_info[control-1].type;
-       if (ctl_mask == 0)
+       if (ctl_mask == 0) {
                cval->channels = 1;     /* master channel */
-       else {
+               cval->master_readonly = readonly_mask;
+       } else {
                int i, c = 0;
                for (i = 0; i < 16; i++)
                        if (ctl_mask & (1 << i))
                                c++;
                cval->channels = c;
+               cval->ch_readonly = readonly_mask;
        }
 
        /* get min/max values */
        get_min_max(cval, 0);
 
-       if (read_only)
+       /* if all channels in the mask are marked read-only, make the control
+        * read-only. set_cur_mix_value() will check the mask again and won't
+        * issue write commands to read-only channels. */
+       if (cval->channels == readonly_mask)
                kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval);
        else
                kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
@@ -1021,8 +1032,8 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                                kctl->id.name, sizeof(kctl->id.name));
 
        switch (control) {
-       case UAC_MUTE_CONTROL:
-       case UAC_VOLUME_CONTROL:
+       case UAC_FU_MUTE:
+       case UAC_FU_VOLUME:
                /* determine the control name.  the rule is:
                 * - if a name id is given in descriptor, use it.
                 * - if the connected input can be determined, then use the name
@@ -1049,9 +1060,9 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                                len = append_ctl_name(kctl, " Playback");
                        }
                }
-               append_ctl_name(kctl, control == UAC_MUTE_CONTROL ?
+               append_ctl_name(kctl, control == UAC_FU_MUTE ?
                                " Switch" : " Volume");
-               if (control == UAC_VOLUME_CONTROL) {
+               if (control == UAC_FU_VOLUME) {
                        kctl->tlv.c = mixer_vol_tlv;
                        kctl->vd[0].access |= 
                                SNDRV_CTL_ELEM_ACCESS_TLV_READ |
@@ -1150,7 +1161,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
                snd_printk(KERN_INFO
                           "usbmixer: master volume quirk for PCM2702 chip\n");
                /* disable non-functional volume control */
-               master_bits &= ~UAC_FU_VOLUME;
+               master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME);
                break;
        }
        if (channels > 0)
@@ -1188,19 +1199,22 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
 
                        for (j = 0; j < channels; j++) {
                                unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize);
-                               if (mask & (1 << (i * 2))) {
+                               if (uac2_control_is_readable(mask, i)) {
                                        ch_bits |= (1 << j);
-                                       if (~mask & (1 << ((i * 2) + 1)))
+                                       if (!uac2_control_is_writeable(mask, i))
                                                ch_read_only |= (1 << j);
                                }
                        }
 
-                       /* FIXME: the whole unit is read-only if any of the channels is marked read-only */
+                       /* NOTE: build_feature_ctl() will mark the control read-only if all channels
+                        * are marked read-only in the descriptors. Otherwise, the control will be
+                        * reported as writeable, but the driver will not actually issue a write
+                        * command for read-only channels */
                        if (ch_bits & 1) /* the first channel must be set (for ease of programming) */
-                               build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, !!ch_read_only);
-                       if (master_bits & (1 << i * 2))
+                               build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, ch_read_only);
+                       if (uac2_control_is_readable(master_bits, i))
                                build_feature_ctl(state, _ftr, 0, i, &iterm, unitid,
-                                                 ~master_bits & (1 << ((i * 2) + 1)));
+                                                 !uac2_control_is_writeable(master_bits, i));
                }
        }
 
@@ -1392,51 +1406,51 @@ struct procunit_info {
 };
 
 static struct procunit_value_info updown_proc_info[] = {
-       { USB_PROC_UPDOWN_SWITCH, "Switch", USB_MIXER_BOOLEAN },
-       { USB_PROC_UPDOWN_MODE_SEL, "Mode Select", USB_MIXER_U8, 1 },
+       { UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+       { UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
        { 0 }
 };
 static struct procunit_value_info prologic_proc_info[] = {
-       { USB_PROC_PROLOGIC_SWITCH, "Switch", USB_MIXER_BOOLEAN },
-       { USB_PROC_PROLOGIC_MODE_SEL, "Mode Select", USB_MIXER_U8, 1 },
+       { UAC_DP_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+       { UAC_DP_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
        { 0 }
 };
 static struct procunit_value_info threed_enh_proc_info[] = {
-       { USB_PROC_3DENH_SWITCH, "Switch", USB_MIXER_BOOLEAN },
-       { USB_PROC_3DENH_SPACE, "Spaciousness", USB_MIXER_U8 },
+       { UAC_3D_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+       { UAC_3D_SPACE, "Spaciousness", USB_MIXER_U8 },
        { 0 }
 };
 static struct procunit_value_info reverb_proc_info[] = {
-       { USB_PROC_REVERB_SWITCH, "Switch", USB_MIXER_BOOLEAN },
-       { USB_PROC_REVERB_LEVEL, "Level", USB_MIXER_U8 },
-       { USB_PROC_REVERB_TIME, "Time", USB_MIXER_U16 },
-       { USB_PROC_REVERB_DELAY, "Delay", USB_MIXER_U8 },
+       { UAC_REVERB_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+       { UAC_REVERB_LEVEL, "Level", USB_MIXER_U8 },
+       { UAC_REVERB_TIME, "Time", USB_MIXER_U16 },
+       { UAC_REVERB_FEEDBACK, "Feedback", USB_MIXER_U8 },
        { 0 }
 };
 static struct procunit_value_info chorus_proc_info[] = {
-       { USB_PROC_CHORUS_SWITCH, "Switch", USB_MIXER_BOOLEAN },
-       { USB_PROC_CHORUS_LEVEL, "Level", USB_MIXER_U8 },
-       { USB_PROC_CHORUS_RATE, "Rate", USB_MIXER_U16 },
-       { USB_PROC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 },
+       { UAC_CHORUS_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+       { UAC_CHORUS_LEVEL, "Level", USB_MIXER_U8 },
+       { UAC_CHORUS_RATE, "Rate", USB_MIXER_U16 },
+       { UAC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 },
        { 0 }
 };
 static struct procunit_value_info dcr_proc_info[] = {
-       { USB_PROC_DCR_SWITCH, "Switch", USB_MIXER_BOOLEAN },
-       { USB_PROC_DCR_RATIO, "Ratio", USB_MIXER_U16 },
-       { USB_PROC_DCR_MAX_AMP, "Max Amp", USB_MIXER_S16 },
-       { USB_PROC_DCR_THRESHOLD, "Threshold", USB_MIXER_S16 },
-       { USB_PROC_DCR_ATTACK, "Attack Time", USB_MIXER_U16 },
-       { USB_PROC_DCR_RELEASE, "Release Time", USB_MIXER_U16 },
+       { UAC_DCR_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+       { UAC_DCR_RATE, "Ratio", USB_MIXER_U16 },
+       { UAC_DCR_MAXAMPL, "Max Amp", USB_MIXER_S16 },
+       { UAC_DCR_THRESHOLD, "Threshold", USB_MIXER_S16 },
+       { UAC_DCR_ATTACK_TIME, "Attack Time", USB_MIXER_U16 },
+       { UAC_DCR_RELEASE_TIME, "Release Time", USB_MIXER_U16 },
        { 0 }
 };
 
 static struct procunit_info procunits[] = {
-       { USB_PROC_UPDOWN, "Up Down", updown_proc_info },
-       { USB_PROC_PROLOGIC, "Dolby Prologic", prologic_proc_info },
-       { USB_PROC_3DENH, "3D Stereo Extender", threed_enh_proc_info },
-       { USB_PROC_REVERB, "Reverb", reverb_proc_info },
-       { USB_PROC_CHORUS, "Chorus", chorus_proc_info },
-       { USB_PROC_DCR, "DCR", dcr_proc_info },
+       { UAC_PROCESS_UP_DOWNMIX, "Up Down", updown_proc_info },
+       { UAC_PROCESS_DOLBY_PROLOGIC, "Dolby Prologic", prologic_proc_info },
+       { UAC_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", threed_enh_proc_info },
+       { UAC_PROCESS_REVERB, "Reverb", reverb_proc_info },
+       { UAC_PROCESS_CHORUS, "Chorus", chorus_proc_info },
+       { UAC_PROCESS_DYN_RANGE_COMP, "DCR", dcr_proc_info },
        { 0 },
 };
 /*
@@ -1524,7 +1538,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
                cval->channels = 1;
 
                /* get min/max values */
-               if (type == USB_PROC_UPDOWN && cval->control == USB_PROC_UPDOWN_MODE_SEL) {
+               if (type == UAC_PROCESS_UP_DOWNMIX && cval->control == UAC_UD_MODE_SELECT) {
                        __u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol);
                        /* FIXME: hard-coded */
                        cval->min = 1;
@@ -1619,7 +1633,7 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_
        struct usb_mixer_elem_info *cval = kcontrol->private_data;
        int val, err;
 
-       err = get_cur_ctl_value(cval, 0, &val);
+       err = get_cur_ctl_value(cval, cval->control << 8, &val);
        if (err < 0) {
                if (cval->mixer->ignore_ctl_error) {
                        ucontrol->value.enumerated.item[0] = 0;
@@ -1638,7 +1652,7 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
        struct usb_mixer_elem_info *cval = kcontrol->private_data;
        int val, oval, err;
 
-       err = get_cur_ctl_value(cval, 0, &oval);
+       err = get_cur_ctl_value(cval, cval->control << 8, &oval);
        if (err < 0) {
                if (cval->mixer->ignore_ctl_error)
                        return 0;
@@ -1647,7 +1661,7 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
        val = ucontrol->value.enumerated.item[0];
        val = get_abs_value(cval, val);
        if (val != oval) {
-               set_cur_ctl_value(cval, 0, val);
+               set_cur_ctl_value(cval, cval->control << 8, val);
                return 1;
        }
        return 0;
@@ -1729,6 +1743,11 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
        cval->res = 1;
        cval->initialized = 1;
 
+       if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
+               cval->control = UAC2_CX_CLOCK_SELECTOR;
+       else
+               cval->control = 0;
+
        namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL);
        if (! namelist) {
                snd_printk(KERN_ERR "cannot malloc\n");
@@ -1778,7 +1797,9 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
                if (! len)
                        strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
 
-               if ((state->oterm.type & 0xff00) == 0x0100)
+               if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
+                       append_ctl_name(kctl, " Clock Source");
+               else if ((state->oterm.type & 0xff00) == 0x0100)
                        append_ctl_name(kctl, " Capture Source");
                else
                        append_ctl_name(kctl, " Playback Source");
@@ -1812,10 +1833,12 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
 
        switch (p1[2]) {
        case UAC_INPUT_TERMINAL:
+       case UAC2_CLOCK_SOURCE:
                return 0; /* NOP */
        case UAC_MIXER_UNIT:
                return parse_audio_mixer_unit(state, unitid, p1);
        case UAC_SELECTOR_UNIT:
+       case UAC2_CLOCK_SELECTOR:
                return parse_audio_selector_unit(state, unitid, p1);
        case UAC_FEATURE_UNIT:
                return parse_audio_feature_unit(state, unitid, p1);
@@ -1912,6 +1935,11 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
                        err = parse_audio_unit(&state, desc->bSourceID);
                        if (err < 0)
                                return err;
+
+                       /* for UAC2, use the same approach to also add the clock selectors */
+                       err = parse_audio_unit(&state, desc->bCSourceID);
+                       if (err < 0)
+                               return err;
                }
        }
 
index 130123854a6cfc37dc2c16cd88281222fa021300..a7cf1007fbb07478fa6a81280174aa919ac8ec4e 100644 (file)
@@ -34,6 +34,8 @@ struct usb_mixer_elem_info {
        unsigned int id;
        unsigned int control;   /* CS or ICN (high byte) */
        unsigned int cmask; /* channel mask bitmap: 0 = master */
+       unsigned int ch_readonly;
+       unsigned int master_readonly;
        int channels;
        int val_type;
        int min, max, res;
index d93fc89beba8aee1040164bccff3935f0a78524d..f1324c423835c8ade54cdb30730e7999b3cec853 100644 (file)
@@ -85,8 +85,8 @@ static struct usbmix_name_map extigy_map[] = {
        /* 16: MU (w/o controls) */
        { 17, NULL, 1 }, /* DISABLED: PU-switch (any effect?) */
        { 17, "Channel Routing", 2 },   /* PU: mode select */
-       { 18, "Tone Control - Bass", UAC_BASS_CONTROL }, /* FU */
-       { 18, "Tone Control - Treble", UAC_TREBLE_CONTROL }, /* FU */
+       { 18, "Tone Control - Bass", UAC_FU_BASS }, /* FU */
+       { 18, "Tone Control - Treble", UAC_FU_TREBLE }, /* FU */
        { 18, "Master Playback" }, /* FU; others */
        /* 19: OT speaker */
        /* 20: OT headphone */
index 056587de7be41876047296cba15a8ea96bd384a9..456829882f4061aca8e97f9d53d07f29d309bd1e 100644 (file)
@@ -31,6 +31,7 @@
 #include "urb.h"
 #include "helper.h"
 #include "pcm.h"
+#include "clock.h"
 
 /*
  * return the current pcm pointer.  just based on the hwptr_done value.
@@ -181,103 +182,6 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
        return -EINVAL;
 }
 
-static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
-                             struct usb_host_interface *alts,
-                             struct audioformat *fmt, int rate)
-{
-       struct usb_device *dev = chip->dev;
-       unsigned int ep;
-       unsigned char data[3];
-       int err, crate;
-
-       ep = get_endpoint(alts, 0)->bEndpointAddress;
-       /* if endpoint doesn't have sampling rate control, bail out */
-       if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) {
-               snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n",
-                                  dev->devnum, iface, fmt->altsetting);
-               return 0;
-       }
-
-       data[0] = rate;
-       data[1] = rate >> 8;
-       data[2] = rate >> 16;
-       if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
-                                  USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
-                                  UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
-                                  data, sizeof(data), 1000)) < 0) {
-               snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
-                          dev->devnum, iface, fmt->altsetting, rate, ep);
-               return err;
-       }
-       if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
-                                  USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
-                                  UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
-                                  data, sizeof(data), 1000)) < 0) {
-               snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
-                          dev->devnum, iface, fmt->altsetting, ep);
-               return 0; /* some devices don't support reading */
-       }
-       crate = data[0] | (data[1] << 8) | (data[2] << 16);
-       if (crate != rate) {
-               snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
-               // runtime->rate = crate;
-       }
-
-       return 0;
-}
-
-static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
-                             struct usb_host_interface *alts,
-                             struct audioformat *fmt, int rate)
-{
-       struct usb_device *dev = chip->dev;
-       unsigned char data[4];
-       int err, crate;
-
-       data[0] = rate;
-       data[1] = rate >> 8;
-       data[2] = rate >> 16;
-       data[3] = rate >> 24;
-       if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
-                                  USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-                                  UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8,
-                                  data, sizeof(data), 1000)) < 0) {
-               snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
-                          dev->devnum, iface, fmt->altsetting, rate);
-               return err;
-       }
-       if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                                  USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                                  UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8,
-                                  data, sizeof(data), 1000)) < 0) {
-               snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
-                          dev->devnum, iface, fmt->altsetting);
-               return err;
-       }
-       crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
-       if (crate != rate)
-               snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
-
-       return 0;
-}
-
-int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
-                            struct usb_host_interface *alts,
-                            struct audioformat *fmt, int rate)
-{
-       struct usb_interface_descriptor *altsd = get_iface_desc(alts);
-
-       switch (altsd->bInterfaceProtocol) {
-       case UAC_VERSION_1:
-               return set_sample_rate_v1(chip, iface, alts, fmt, rate);
-
-       case UAC_VERSION_2:
-               return set_sample_rate_v2(chip, iface, alts, fmt, rate);
-       }
-
-       return -EINVAL;
-}
-
 /*
  * find a matching format and set up the interface
  */
index 06ebf24d3a4d504e61840f5abca7a30a87b5d5e1..24d3319cc34d0985ace0270be5b7894a3b086c21 100644 (file)
@@ -40,9 +40,6 @@ struct snd_usb_audio {
        int num_interfaces;
        int num_suspended_intf;
 
-       /* for audio class v2 */
-       int clock_id;
-
        struct list_head pcm_list;      /* list of pcm streams */
        int pcm_devs;
 
@@ -53,6 +50,8 @@ struct snd_usb_audio {
        int setup;                      /* from the 'device_setup' module param */
        int nrpacks;                    /* from the 'nrpacks' module param */
        int async_unlink;               /* from the 'async_unlink' module param */
+
+       struct usb_host_interface *ctrl_intf;   /* the audio control interface */
 };
 
 /*
index 7c79c1d76d0c13e72463fcddc00cf845ad63ca87..3500dee9cf2b24e7a6965f67d198d6e290798f9e 100644 (file)
@@ -192,12 +192,13 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
 
 int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
 {
-       u32 old_irr = ioapic->irr;
+       u32 old_irr;
        u32 mask = 1 << irq;
        union kvm_ioapic_redirect_entry entry;
        int ret = 1;
 
        spin_lock(&ioapic->lock);
+       old_irr = ioapic->irr;
        if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
                entry = ioapic->redirtbl[irq];
                level ^= entry.fields.polarity;
index d2f06be63354b1b43555f3e491bf61ce6cac8c6c..96048ee9e39e8f57d068f558cd4888961c46aa42 100644 (file)
@@ -271,7 +271,7 @@ static void kvm_iommu_put_pages(struct kvm *kvm,
                pfn  = phys >> PAGE_SHIFT;
 
                /* Unmap address from IO address space */
-               order       = iommu_unmap(domain, gfn_to_gpa(gfn), PAGE_SIZE);
+               order       = iommu_unmap(domain, gfn_to_gpa(gfn), 0);
                unmap_pages = 1ULL << order;
 
                /* Unpin all pages we just unmapped to not leak any memory */